Кризис современных языков. Как абстракции, «наслаиваясь» с 1972 года, убивали производительность
30.06.2018 11:32
—
Разное
|
Когда-то давным-давно не существовало понятия «язык программирования». Существовало только «программирование голого железа» (bare metal programming) и шутка на (Чтобы дать компьютеру необходимые указания к действию до появления программирования с помощью перфокарт, обычно требовалось каким-то образом модифицировать аппаратную платформу. Но если зайти дальше Бесспорно, такой вид программирования был невероятно трудным, нудным и не защищённым от ошибок. Языки ассемблера на основе текста появились уже во времена перфокарт, дав программистам что-то по крайней мере читаемое для человека (в самом общем смысле слова «читаемый», да и слова «человек» — тоже), но соответствие между программой и аппаратной платформой было практически 1:1. Настоящим прорывом стало появление языков высокого уровня: Fortran в 1957 году, ALGOL в 1958, BASIC в 1964, Pascal в 1968 и наконец Си в 1972 году, — причём с появлением последнего в программировании произошли поистине коренные изменения. Си был не первым языком высокого уровня, и даже сам по себе он не был революционным, но это — единственный из третьего поколения языков, который и по сей день имеет значительное применение. Секрет успеха Си больше, чем просто удача. Он состоит в том, что создавался язык с целью написания операционной системы — задача, которая раньше поручалась языку ассемблера. Поэтому Си с его небольшим набором элементарных конструкций предоставлял возможность слаженно взаимодействовать с аппаратной основой на довольно примитивном уровне (обеспечивая плавный перевод c ассемблерного кода и на него), а также создавать абстракции почти произвольной сложности. Мне неизвестно их количество и как его оценить в принципе, но рискну предположить, что 99,999 процента всего кода, работающего на всех компьютерах в мире —
Си — потрясающе эффективный язык, но и он в конце концов начал считаться трудным, нудным и не защищённым от ошибок, и над ним начали появляться абстракции. С++, разработанный в 1985 году, был одним из первых, но в определённом смысле — самых простых: по сути, С++ — это надмножество Си, дающее программисту свободу использовать объектно-ориентированные конструкции. С++ компилируется в тот же самый машинный код, что и Си, и может (по крайней мере в теории) достаточно просто скомпилироваться в Си, что первым компиляторам С++ и было под силу. Но С++ больше не единственный язык, устроенный таким образом: в последние годы возрождается популярность категории (2), включающей более высокоуровневые, чем Си, языки системного программирования. В основном это происходит из-за бесконтрольного раздувания стандарта С++, а также растущего признания проблемы, о которой я расскажу ниже. В приложениях, где крайне важную роль играет производительность (вернее, когда производительность недостаточно велика, так как она всегда играет важную роль, независимо от того, понимают ли это люди), С++ вне конкуренции. Сегодня потеснить его пытается Rust, который можно считать лучшим альтернативным системным языком этого поколения, но С++ не собирается сдавать позиции (по крайней мере пока Rust не начнёт легко интегрироваться с Си, но даже в таком случае происходить это будет очень медленно и до конца никогда не произойдёт).
На деле результатом стал взрывной и (с чем можно поспорить) неустойчивый рост категории (3) — интерпретируемых языков. Если забыть о BASIC, начало ему в 1995 году положил Java. Идея была проста и разумна: интерпретация (в данном случае байткода) не должна зависеть от ОС и аппаратной основы, благодаря чему разработчики смогут поставлять один «двоичный код» всем своим клиентам. Абстрагирование от ОС в дальнейшем улучшило безопасность, хотя и не настолько, чтобы можно было свободно исполнять сомнительный код по сети. Но на другой стороне медали производительность: в 1995 она была гораздо более существенной проблемой, чем сегодня, но до сих пор остаётся досадным минусом для тех, кто имел несчастье, например, познакомиться с Eclipse. (По той же причине инструменты командной строки на Java даже хуже: скорость виртуальной машины Java в процессе весьма неплоха, но для её запуска требуется масса времени.) Один нюанс Java в том, что он почти ничем не превосходит С++ в плане абстракции. Он фактически независим от платформы, но с появлением современных кросс-платформенных библиотек и инструментов DevOps, отсутствие этого свойства у С++ практически нивелируется. Разрабатывать на Java не проще, управление памятью на нём ненамного больше автоматизировано (куда делись динамически растущие массивы?), типизация, пожалуй, лучше, чем в Си (в Java можно получить сообщение об ошибке, если попытаться преобразовать класс к самому себе), и ещё в Java есть эти жуткие нулевые указатели — единственная самая ненадёжная в отношении ошибок деталь из всех, что есть в Си. Безопасность едва ли лучше той, которой обладала Unix где-то за 20 лет до того, как мир узнал о «байткоде», и абсолютно недостаточна с учётом того, как люди исполняют код сегодня. (То есть ненадёжный, непроверенный код и часто удалённо, по всей сети.) Однако в результате упадка Java не вернулись к прежним, нативным стандартам, а перешли на ещё более высокий уровень абстракции. JavaScript, абсолютно не связанный с Java, тоже появился в 1995 году, но почти полтора десятилетия томился в безызвестности, пока Apple не решила поставить Flash на iPhone, чем и положила начало разработке нового стандарта без установки дополнительных плагинов для так называемого «веб 2.0». Современное веб-приложение в некотором смысле решало все проблемы Java и даже больше: полностью кросс-платформенное, предоставляется автоматически, ничего не меняет в системе пользователя, даже если бы он и захотел. Кроме того, такие приложения проще разрабатывать. В JavaScript тяжелее ошибиться (хотя писать правильно намного сложнее, но это уже никого не волнует), а также он гораздо больше подходит для проектирования (и особенно тематического оформления) UI на языке разметки, стоящего особняком от «настоящего» программирования. Сегодня в вебе огромную роль играют Chrome OS and Electron, а серверы на Node используют JavaScript. Нравится нам это или нет (а есть множество аргументов в пользу обоих мнений), но именно в этом направлении развивается современная разработка приложений. Только веб, всегда. Здесь можно задать вполне уместный вопрос: если у вас есть коммерчески жизнеспособная ОС с единственным приложением — браузером, то это минималистичная ОС или непомерно Называть Chrome операционной системой не будет преувеличением. По количеству строк кода он почти сравним с ядром Linux. Как и у ядра Linux, у него есть API для самых разных аппаратных основ, включая OpenGL, VR, MIDI. В него интегрированы SQLite, менеджер памяти и собственный диспетчер задач. На macOS у него есть даже драйвер USB для контроллеров Xbox 360. (Я знаю это, потому что сам его написал.) В Slack, например, нет моего кода для контроллеров Xbox. На самом деле, как операционная система Chrome может быть даже лучше, чем большинство дистрибутивов Linux — по крайней мере, он проще для разработчиков. В нём нет проблем с унаследованным мусором и Но дело в том, что всё это основано JavaScript, языке, который был Не то чтобы этого никто не сделал. Самый известный и, возможно, самый быстрый движок JavaScript сегодня — это V8 от Google, движок, который является важным компонентом Chrome (а также Node и Electron). Его название, несомненно, должно ассоциироваться с мощным автомобильным двигателем, но если бы V8 был автомобильным двигателем, то не был бы V8. Если отталкиваться от сложности и затрат на обслуживание, ему больше подошло бы название «W16» — как у 8-литрового с четырьмя турбинами двигателя Bugatti Veyron, в котором замена масла обходится в $21 тысячу. Возможно, использовать V8 Google не совсем то же самое, что разъезжать на гиперкаре стоимостью $1,7 млн, но расход топлива (оперативной памяти) будет сопоставим. Но в данном случае вам хотя бы не вы будете менять масло. Но если бы топливо (и Bugatti) были бесплатны, мы вполне могли бы стали пользоваться ими для повседневных поездок. По сути, в такую ситуацию и поставил нас закон Мура: если 10-процентый прирост производительности или снижение расхода ресурсов (а это нелёгкое дело для крупного проекта) достигается за три месяца, оптимальным решением будет отказаться от оптимизации и просто расширять программный стек. Закон Мура пока что спасал нас от последствий, показанных Тот факт, что количество выполняемого нами кода растёт в геометрической прогрессии, в настоящее время не имеет значения, потому что скорость наших процессоров также растёт в геометрической прогрессии, причём гораздо более быстрыми темпами. Но закон Мура не может выполняться вечно, и не в нём дело. Квантово-механические пределы размера транзисторов уже не за горами. Новые технологии, необходимые, чтобы продолжать разрабатывать лучшие и более быстрые процессоры — намного дальше за горизонтом. Рано или поздно наступит период — и, может быть, долгий, — когда вычислительная мощность (по крайней мере по отношению к цене) практически застынет на одном уровне — по крайней мере в сравнении с ростом, который она пережила во времена закона Мура. И когда этот момент настанет (предсказывают, что это произойдёт уже в 2021 году), то бурный рост кодовой базы действительно станет опасным. Кроме того, закон Мура позволил не только ускорить, но и удешевить компьютеры. У людей, которые прежде никогда не могли бы позволить себе домашний компьютер, теперь есть как минимум смартфон, и ассортимент предлагаемых сегодня устройств широк, как никогда. Вместе эти два детали и знаменуют надвигающийся кризис: концепция «запланированного устаревания» товаров вскоре рухнет. Что в это время будет с вами? Веб-разработчики не будут к этому готовы, потому что общий курс веб-разработки, кроме несколько обнадёживающих исключений, — не на упрощение кода или уменьшение уровней абстракции. Напротив, многие веб-приложения (если не большинство) сегодня строятся в гигантских фреймворках, из-за чего появляется ещё больше уровней абстракции и сложности поверх 4 турбин вашего W16. Люди хотят строить приложения за полчаса, и в этом им Не сказать, чтобы вопрос с производительностью был решён. Использование CPU уже не (самая большая) проблема, потому что на вебе код необходимо скачивать при каждом его запуске. В приложении на React должно быть (Шокирующая статистика из этой статьи — что в приложении Facebook под iOS содержится 18 тысяч классов Objective-C — объясняется принципом работы React, но это уже отдельная тема). Возможно, есть фреймворки получше, но насколько они лучше? Даже jQuery весит 86 килобайт: крошечный по сегодняшним меркам, он всё равно зачастую тяжелее кода, который его использует. Говоря о массивности некоторых из этих фреймворков, нужно иметь в виду, что причиной тому — именно JavaScript, выполняемый в виртуальной машине, которая в свою очередь занимает миллионы строк в операционной системе размером в десятки миллионов строк. Не все они должны исполняться для каждой отдельной строки JavaScript — многие могут вообще никогда не исполняться, но и та небольшая доля, что исполняется, всё равно составляет порядочное количество кода. Сколько займёт на Си 80-тысячый код на JavaScript? И сколько строк займёт код достойного аналога React.js с простым языком разметки UI и API на С++? Может и больше 80 тысяч. (Qt, который может всё, что может React, и много чего ещё, и едва ли отличается простотой, занимает около 470 тысяч строк на С++ — это почти в 6 раз больше 80 тысяч, но в 4 раза меньше размера V8 и в 20 раз — Chrome.)
Первым делом нужно устранить наихудшее, что есть в культуре веб-фреймворков. Если честно, возможность строить приложения моментально или даже бы за 24 часа — бесполезная вещь, от которой больше вреда, чем пользы. Вряд ли специалисты Google могут быть настолько самоуверенными, чтобы думать, что смогут построить настоящий полноценный продукт за полчаса, но и демонстрировать проект полному залу разработчиков тоже кажется безответственным — вдруг будут шпионить Нельзя сказать, что человек, способный создать нечто стоящее, способен создать это нечто с нуля (так и не должно быть), но что произошло бы с качеством ПО, если бы все программисты мыслили таким образом? Далее, поставщикам ОС и браузеров нужно усовершенствовать свои API. Например, jQuery, по сути, стал стандартом в современном вебе — его API далеко превосходят слабенькие стандартные интерфейсы DOM. Очевидно, создателям браузеров нужно просто встроить в них (по крайней мере ключевое подмножество) jQuery — так этот достаточно частый код можно будет использовать вместо JavaScript и избавиться от загрузки фактически миллиардов страниц по 86 килобайт каждая. То же самое касается и сторонних библиотек на десктопе: нет примера более наглядного, чем jQuery, но они определённо есть, возможно,
WebAssembly наконец стал прямо поддерживаемой альтернативой JavaScript в браузере, далее переход на WebAssembly должен стать главной и в конечном итоге единственной целью. Чтобы сделать это с минимальными потерями, нужно найти способ скомпилировать существующий JavaScript в WASM, а это непросто — вспомните проблему с W16 выше. И всё же существующие JS-движки компилируют JavaScript, поэтому не составит особой трудности делать дамп кода на диске (наверно, в виде байткода LLVM) вместо того, чтобы сразу же запускать его. Наконец, нужно убрать всё лишнее между аппаратной основой и непосредственно написанием ПО. В знаменитом выступлении
И каждый последующий слой, добавленный в наш программный стек, становится ещё больше раздутым, как красный гигант на закате своей жизни, который рано или поздно превратится в сверхновую звезду. Разработке нужно не более и не менее того, что было в 1972 году: система, в которой разработчики могут строить приложения с использованием простых API, настолько близко к аппаратной платформе, насколько это позволяет безопасность. Проблема заключается в том, что системы, которые функционируют близко к аппаратной основе, были созданы практически на технологии 1972 года и с того времени существенно не видоизменялись. В результате вполне предсказуемо один за другим накладывались слои абстракций, убивающих производительность. Хотя этого можно было избежать. И надеюсь, ещё не поздно исправить. Чтобы разместить новость на сайте или в блоге скопируйте код:
На вашем ресурсе это будет выглядеть так
Брент Бессемер написал статью о кризисе современных языков программирования. dev.by приводит её перевод. Читать далее...
|
|