как код превращается в программу
Как компьютер преобразовывает программный код в то, что мы в итоге видим на экране?
Это очень обширный вопрос. На него можно ответить парой строк, а можно написать целую библиотеку научных книг (правда, зачем их писать, они уже написаны).
Один человек говорит что-то в микрофон (аналогия программы в компьютере), а другой человек слышит, что было сказано (аналогия картинки на экране). Как это работает?
Микрофон преобразует звуковые колебания (речь) в аналогичные колебания электрического тока. И вот с этого момента начинаем смотреть. Провод микрофона (в котором ток) соединён с электрической схемой (провода, катушки, транзисторы, вот это вот всё). Когда ток есть (что-то сказали в микрофон), электроны (из которых ток состоит) начинают приходить в транзистор. Когда они туда приходят, поведение транзистора меняется, он начинает пропускать ток по-другому. Можно сказать, что ток (от микрофона) управляет поведением транзистора. Что представляет из себя транзистор? Грубо говоря, это такая электрическая штука с тремя ножками (проводами). Он очень ценен тем, что при помощи него можно выполнять что-то вроде простейших арифметических действий. Что это значит? Допустим, на одну ножку мы подаём какой-то ток. Он свободно течёт с первой ножки на третью. А на вторую ножку мы подаём другой ток, который сам по себе не столько куда-то течёт, сколько управляет тем, насколько легко ток течёт из первой ножки в третью. Получается что-то вроде процесса умножения. Если мы «поддадим» тока на вторую ножку, ток с первой ножки в третью начнёт течь активнее. Если мы, уберём ток со второй ножки, ток с первой на третью, быть может, вообще не сможет течь. При этом, конечно, мы можем изменять не только ток на второй ножке, но и ток на первой. Если на первой ножке ничего нет, то и на третьей ножке ничего не окажется.
Выстроив при помощи транзисторов (и прочих штук, в которые, для простоты, мы сейчас вникать не будем) нужную нам схему, мы получаем нужное нам поведение тока на выходе. Для радио, в частности, это поведение заключается в том, что мы наносим голосовой сигнал (с микрофона) на т. н. «несущую частоту» (быстрые колебания, которые хорошо превращаются в электромагнитное поле с помощью антены). Потом в радиоприёмнике происходит обратный процесс, сигнал «очищается» от несущей частоты и подаётся на динамик, который звучит и, в итоге, повторяет сказанное.
А теперь давайте представим радиопередатчик, который передаёт сигнал радиоприёмнику, а радиоприёмник не только преобразует его в звук, но ещё и как-то этот звук меняет. Радиоприёмник будет издавать звук, но другой. А если рядом поставить микрофон, передатчик и опять этот звук куда-нибудь отправить? Мы получили простейший пример (может быть, немного несуразный), когда «машина» разговаривает сама с собой.
Теперь давайте быстро разберём общую концепцию компьютера. Для простоты давайте придумаем упрощённый вариант компьютера.
Это была одна команда. Далее процессор берёт число из следующего адреса. Для того, чтобы знать, откуда брать числа, которые являются программой, у процессора есть регистр, в котором он хранит текущий адрес команды. Каждый раз, как он берёт очередную команду, он прибавляет к этому регистру единичку (для этого опять существует целая схема, которая умеет складывать числа). Поэтому процессор каждый раз берёт число из следующих 64 конденсаторов памяти. Так он движется число за числом и делает что-то полезное. Например, следующим числом, будет число, которое означает «возьми из адреса (который, как обычно, будет указан далее) число и запиши его во второй регистр». Потом будет «возьми число (адрес указан далее) и запиши в третий регистр». Потом, например, «вычти из числа в первом регистре число второго регистра и результат запиши снова в первый регистр». Потом «если в первом регистре сейчас ноль, поменяй число в счётчике адреса на число, которое сейчас находится в третьем регистре» (есть и такая команда).
Что, в итоге, произошло? Процессор взял два числа из памяти и сравнил их между собой. Если эти два числа равны (в этом случае после вычитания получился ноль), процессор вместо того, чтобы выполнить команду, которая должна была быть следующей, установил в регистре адреса новое число. Поэтому следующую команду он возьмёт из какой-то другой части памяти и там будет уже другая программа.
На этом примере мы увидели, как процессор проявляет признаки разума. Он оценивает ситуацию (равны ли числа) и, в зависимости от результата, начинает делать либо одно, либо другое.
Ну а как всё это вывести на экран? Это уже просто. Существует видеокарта. Это отдельная схема со своей собственной памятью. При этом, допустим, 60 раз в секунду, видеокарта «сканирует» свою память и поочерёдно, число за числом, записывает сигнал в видеовыход. Только она не выдаёт число по 64 проводам (как мы это делали раньше) а сперва преобразует число: чем больше это число, тем сильнее видеокарта подаёт ток. В итоге мы получаем, что сила тока соответствует величине числа. Этот провод идёт к монитору. Монитор же, поочерёдно, выводит этот сигнал точка за точкой. В мониторе есть красные, зелёные и синие точки (очень мелкие, может потребоваться лупа). Чем сильнее ток в этот момент, тем ярче зажигается точка.
То есть, операционная система (которая является очень сложной программой) содержит в себе программу, которая управляет рисованием на экране. Когда нужно что-то показать на экране, эта программа начинает записывать нужные числа в память видеокарты. А видеокарта превращает эти числа в сигнал для монитора и монитор это показывает (на самом деле, так было лет 10 назад, сейчас уже мониторы, по сути, тоже являются простеньким компьютером, который получает картинку в виде чисел, сам рисует разные меню настройки и пр., но это уже частности).
Программирование с нуля
Данная статья описывает основные конструкции в программировании и предназначена для тех, кто хочет в этом разобраться. Но статья не описывает все нюансы, потому что их слишком много. Если описывать их все, будет очень нудно и непонятно.
Использовать будем си-подобный синтаксис, то есть подобный языку си, но не будем вникать в заголовочные файлы, указатели и другие особенности относительно низкоуровневых языков, перейдём на синтаксис более высокоуровневых языков, которые сделают рутинную работу за нас. А конкретно, будем использовать синтаксис языка Java. Добро пожаловать под кат.
Двоичная система счисления
Числа в двоичной системе счисления состоят всего из двух знаков. Нуля и единицы. 00000001 – число один. 00000010 – число два. 00000100 – число 4. Как вы можете заметить, когда единица смещается влево, число увеличивается в два раза. Чтобы получилось число 3, необходимо написать 00000011. Таким образом можно составить все необходимые числа. В данном примере мы использовали двоичное число с восемью знаками, иначе говоря число восьмиразрядное. Чем больше у числа разрядов, тем большее оно может вместить значение. Например, восьмиразрядное число вмещает максимальное значение 255, если считать ноль, тогда 256, а в программировании ноль считается всегда. Если увеличить разряд на один, получится девятиразрядное число и его вместимость увеличится в два раза, то есть станет 512. Но так в программировании никогда не делается и обычно каждая следующая разрядность увеличивается вдвое. Один разряд, потом 2 разряда, потом 4 разряда, потом 8 разрядов, потом 16 разрядов, потом 32 разряда и далее.
Шестнадцатеричная система счисления
Всё аналогично двоичной, только вместо нулей и единиц участвуют цифры от 0 до 15. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, где A – 10, B – 11, C – 12, D – 13, E – 14, F – 15.
Знак минус в программировании
Буквы и знаки
Буквы, знаки, смайлики и так далее обозначаются также числами. Буква А может быть числом 00000001 или любым другим, или даже комбинацией чисел в зависимости от кодировки символов. Кодировок много.
Типы данных
В программировании есть типы данных. Числовые, такие как 233, которые разобрали выше. Называются почти везде int, от слова integer. С плавающей запятой, такие как 198,76, называются почти везде float. У букв тип char, у строк тип String. Тип bool имеет два значения – истина (true) и ложь (false). У этого типа реализация в разных языках разная, но самая простая, когда ноль — значит ложь, а любое другое число истину. Нестандартные типы данных, такие как числа с фиксированной запятой, рассматривать не будем.
Применение
Прежде чем использовать числа в программировании их нужно объявить, то есть сказать с помощью языка программирования, что они существуют.
Это стандартное объявление примитивного типа.
Сначала пишем тип, потом имя переменной, то есть нашего числа. Всегда заканчиваем наше выражение, да и любое, точкой с запятой.
Теперь мы можем использовать переменную по её имени.
Здесь мы присвоили переменной значение. В отличии от математики в программировании = значит взять значение справа и присвоить переменной слева. = — это знак/оператор присвоения.
Можно объединить объявление и присвоение, то есть сразу инициализировать переменную.
Буквы выделяются одинарными кавычками, строки выделяются двойными кавычками. Числа типа int не выделяются.
К числам с плавающей запятой одинарной точности в конце добавляется f.
К числам с плавающей запятой двойной точности ничего не добавляется.
Операторы
После того как мы записали наше выражение, например сложения,
получается значение. Но так как оно ни одной переменной не присваивается, оно исчезает. Чтобы присвоить значение переменной используется специальный оператор присвоения, который коротко описан выше.
Повторим ещё раз. Он берёт значение со своей правой стороны и присваивает его переменной в левой стороне. Это оператор =, и он не имеет ничего общего со знаком равно из математики.
Также у нас есть логические операторы, такие как (больше),
Исходный код: что нужно знать, чтобы успешно защитить права на программное обеспечение?
Программное обеспечение — специфический объект авторских прав. Программы обладают рядом технических характеристик, которые нужно учитывать, чтобы успешно защищать интересы правообладателей. Что такое исходный код программы? Как доказать, что программу украли? Какие методы защиты прав на программное обеспечение наиболее эффективны?
Рассказывает:
Роман Янковский,
советник практики IP & IT юридической фирмы «Томашевская и партнеры»
ГК РФ определяет программу для ЭВМ как совокупность данных и команд, предназначенных для функционирования компьютерных устройств. Программы могут быть выражены на любом языке и в любой форме, включая исходный текст и объектный код (ст. 1261 ГК РФ).
Благодаря такому определению многие юристы воспринимают исходный код программы как текст наподобие литературного произведения. Базовое представление о программе: это некие строки, которые компьютер читает и выполняет по очереди, и таким образом программа работает. Однако такое понимание не учитывает технические нюансы, которые влияют на возможность защиты права на программу.
Какие технические особенности влияют на защиту кода?
Особенность № 1
Большинство языков программирования являются компилируемыми. Это значит, что получить исходный текст чужой программы невозможно, если вам не передал его сам разработчик.
Языки программирования бывают интерпретируемыми и компилируемыми. Программу на интерпретируемом языке программирования компьютер, грубо говоря, построчно читает. Но на практике такие языки программирования используются достаточно редко.
Большинство программ сегодня пишут на компилируемых языках программирования. Такие программы работают только после прохождения специальной процедуры компиляции. Программа-компилятор собирает исходный текст программы, написанной, упаковывает и изменяет его и выдает так называемый исполняемый файл (обычно с расширением «.exe» – от англ. “executable”).
Иными словами, компилятор преобразует исходный текст программы в объектный код, и только после этого программу можно запустить на компьютере.
А куда делся исходный текст программы, который написал программист при разработке программы?
Компилятор преобразовал его в объектный код. Мы не можем вернуть его обратно. Максимум, что мы можем сделать с объектным кодом, — представить его в виде так называемых ассемблерных команд. Ассемблерные команды — это максимально очеловеченное и удобочитаемое представление машинного кода (хотя об удобочитаемости тут можно говорить весьма условно).
Таким образом различают:
Теоретически небольшую программу можно сразу написать на языке низкого уровня (используя ассемблерные команды). Но сейчас так никто не делает, потому что написать даже простую программу на ассемблере — это большой объем работы. Программы пишут на языках программирования высокого уровня в виде исходного текста. Затем, как мы уже говорили, компилятор обрабатывает этот текст и превращает его в смесь цифр и букв – объектный код.
Какое значение это имеет для юристов?
Исходный текст есть только у разработчика программы. Когда разработчик распространяет программу, он делает это в виде скомпилированного файла. Технически из этого файла можно получить только объектный код.
Есть процедура так называемой декомпиляции: специалист пытается воссоздать первоначальный код из ассемблерных команд. Согласно ГК РФ, декомпиляция – это воспроизведение и преобразование объектного кода в исходный текст (ст. 1280 ГК РФ). Однако важно понимать, что даже если специалист смог воссоздать код на языке высокого уровня, который генерирует необходимый объектный код (то есть, по сути, восстановил программу), этот код высокого уровня не будет аналогичен первоначальному. То есть этот «исходный текст» не будет исходным в прямом смысле этого слова: после декомпиляции мы не получим исходный текст, который изначально разработчик обработал компилятором.
Из-за этого у правообладателей возникают сложности с тем, чтобы доказать нарушение прав на программное обеспечение.
В файле программы нет исходного текста. Если ваши права нарушены, вы можете только, грубо говоря, показать чужую программу в суде и сказать, что она очень похожа на вашу и делает то же самое. Однако до суда у вас не будет исходного текста чужой программы, чтобы подтвердить ее тождественность с вашей.
Чтобы доказать нарушение, потребуется судебная экспертиза. Для этого нужно через суд запросить исходный текст у потенциального нарушителя. Но здесь нужно учитывать, что под видом исходного текста оппонент может передать абсолютно сторонний файл. Поэтому правообладателю придется перепроверить, что на выходе переданный исходный текст действительно представляет собой спорную программу.
Особенность № 2
Программы занимают физически очень большой объем.
Количество строк кода в совсем небольшой игре для телефона сопоставимо с количеством строк в ГК РФ. Серьезные программы занимают значительно больший объем. Поэтому не так просто принести в суд распечатку кода своей и чужой программ и сравнить их: это будут две огромные кипы бумаги.
Есть и другой нюанс. Программы могут быть практически идентичны, при этом код в них может быть структурирован по-разному. Технически это возможно – расположение отдельных блоков кода в программе можно менять. В такой ситуации выявить сходство с учетом объема программы будет непросто даже разработчику.
Особенность № 3
Программы постоянно обновляются.
В программы постоянно вносятся изменения. Если программа объемная, то новые версии могут появляться несколько раз в день. Соответственно, у нее нет постоянного кода, который можно было бы депонировать раз и навсегда.
Особенность № 4
Большинство программ пишут на основании уже готового кода.
Программы сегодня не создаются с нуля. Разработчики пишут большинство программ на основе уже готовых модулей, так называемых библиотек. Они бывают платными и бесплатными. Бесплатные библиотеки часто распространяются на условиях открытой лицензии, что представляет проблему для юристов.
Дело в том, что разные типы свободных лицензий накладывают разные обязательства на правообладателя программы, в которой используется готовая библиотека. Так, по одним лицензиям права на библиотеку переходят в общественное достояние и могут использоваться кем угодно. По другим, наоборот, использование библиотек в составе коммерческих программ либо совсем запрещено, либо возможно лишь при условии раскрытия кода (то есть публикации результата в открытом доступе).
Есть два способа внедрить чужую библиотеку в свою программу:
На заметку
Не всё, что юристы называют «программой», выполняет какую-то активную функцию. Например, для создания сайтов используют так называемые языки гипертекстовой разметки. Сайты тоже имеют код, который не отображается при открытии сайта, но отвечает за его техническую функциональность. При этом такой код не является программой в традиционном понимании — это скорее что-то настроек отображения сайта, которые передаются пользователю и обрабатываются его браузером. Поэтому в разных браузерах сайты могут выглядеть по-разному, тогда как команда обычно выдает один и тот же результат на разных компьютерах.
Как оформить и защитить права на программу?
Возможны несколько вариантов оформления прав на программу, чтобы в последующем можно было отстоять права на нее.
Программа для ЭВМ является объектом авторского права. По ГК РФ регистрация для защиты авторских прав не требуется (ст. 1259 ГК РФ).
Однако для программ для ЭВМ такая регистрация возможна: специальный реестр ведет Роспатент. Реестр программ для ЭВМ открыт с 2013 года. Регистрация программы в реестре добровольная.
Переход прав на зарегистрированные программы тоже регистрируется. Также в реестре можно отдельно регистрировать каждую версию программы. Это имеет смысл, если изменения были существенными. Можно зарегистрировать программу любого объема.
Обратите внимание, что код программы не индексируется и не проверяется на работоспособность. Кроме того, новый код не сверяют с кодами, зарегистрированными ранее.
Самое главное: регистрация в реестре не считается правопорождающим фактом. А сам реестр не считается публичным – перед покупкой программы у покупателя нет обязанности проверять в реестре, является ли продавец ее правообладателем.
По сути, регистрация в этом реестре представляет собой механизм добровольного депонирования. Автором программы считается лицо, указанное в реестре, но только пока не доказано иное (п. 6 ст. 1262 ГК РФ, п. 109 Постановления Пленума ВС РФ от 23.04.2019 № 10 «О применении части четвертой Гражданского кодекса Российской Федерации»).
На заметку
Существуют альтернативные способы депонирования программ. Например, у ВОИС недавно появилась услуга онлайн-депонирования интеллектуальных активов. Правда, пока нет практики использования таких сертификатов в качестве доказательств, потому что этот механизм совсем новый – работает с июня 2020 года.
ГК РФ напрямую не предусматривает такой способ защиты прав на программы. Наоборот, в законе указано, что программа для ЭВМ не является изобретением (ст. 1350 ГК РФ). Поэтому при патентовании программы как таковой можно столкнуться со сложностями.
Роман Янковский рекомендует патентовать не саму программу, а алгоритм ее работы. Такие патенты встречаются на практике (например, есть патенты на решения для распределенного реестра).
В качестве примера можно привести спор между приложением для знакомств Tinder и его конкурентом – Bumble. Сервис-конкурент запустили бывшие сотрудники Tinder. У обоих приложений были очень похожие функции, в частности механизм «свайпа», на который у Tinder был патент на промышленный образец.
Распространить режим коммерческой тайны на разработанный софт и потребовать от работников подписать соответствующие документы – это хорошее решение по двум причинам:
СОДЕРЖАНИЕ
Набор инструкций
В наборе команд процессора могут быть все команды одинаковой длины или могут быть команды переменной длины. Как организованы шаблоны, зависит от конкретной архитектуры и типа обучения. Большинство инструкций имеют одно или несколько полей кода операции, которые определяют базовый тип инструкции (например, арифметическая, логическая, переход и т. Д.), Операцию (например, сложение или сравнение) и другие поля, которые могут указывать тип операнда (s ), режим (ы) адресации, смещение (а) адресации или индекс, или само значение операнда (такие постоянные операнды, содержащиеся в инструкции, называются немедленными ).
Программ
На выполнение программы могут влиять специальные инструкции «перехода», которые передают выполнение на адрес (и, следовательно, инструкцию), отличный от следующего числового последовательного адреса. Возникновение этих условных переходов зависит от такого условия, как значение, которое больше, меньше или равно другому значению.
Языки ассемблера
Пример
Например, сложение регистров 1 и 2 и помещение результата в регистр 6 кодируется:
Загрузите значение в регистр 8, взятое из ячейки памяти 68 ячеек после ячейки, указанной в регистре 3:
Переход по адресу 1024:
Связь с микрокодом
Использование микрокода для реализации эмулятора позволяет компьютеру представить архитектуру совершенно другого компьютера. Линия System / 360 использовала это, чтобы позволить переносить программы с более ранних машин IBM на новое семейство компьютеров, например, эмулятор IBM 1401/1440/1460 на IBM S / 360 model 40.
Связь с байт-кодом
Машинный код и ассемблерный код иногда называют собственным кодом, когда речь идет о платформенно-зависимых частях языковых функций или библиотек.
Хранение в памяти
Читаемость людьми
Машинный код для интернета. Как Javascript превращается в подобие ассемблера
Содержание статьи
Закон Атвуда гласит, что любое приложение, которое можно написать на Javascript, однажды напишут на Javascript. Компилятор Emscripten делает это практически неизбежным.
Интро
Чтобы запустить в браузере Linux или игру для старинной видеоприставки, можно использовать виртуальную машину, написанную на Javascript. Но это не единственный и даже не лучший способ.
Первая проблема связана с тем, что эмуляция железа заведомо менее эффективна, чем исполнение нативного кода. Это знают и сами разработчики эмуляторов. Когда скорости пошагового моделирования работы чужого процессора не хватает, им приходится добавлять динамическую рекомпиляцию — автоматический перевод участков эмулируемого кода в Javascript. Это трудно, но после переработки умным JIT-компилятором код становится быстрее.
Кроме того, до эмуляции железа нужно ещё добраться. Это совсем не простая задача, и тот факт, что она зачастую уже решена (просто не на нужном Javascript, а на другом языке программирования), вовсе не прибавляет энтузиазма. Переписывать десятки, а то и сотни тысяч строк кода с Си на Javascript — удовольствие на любителя. Люди, которым интересен этот процесс, безусловно, встречаются, но куда реже тех, кто предпочитает результат.
Frontend и Backend
Один из создателей Javascript однажды заметил, что этот язык превратился в своего рода машинный код для интернета. Существуют компиляторы, которые переводят в Javascript программы, написанные на Python, Java и Smalltalk. Некоторые языки с самого начала рассчитаны на переработку в Javascript — к этой категории относятся Coffeescript и используемый React.js формат JSX.
У подобного подхода долгая история, которая началась задолго до появления Javascript и даже браузеров. В прошлом компиляторы многих языков программирования не могли генерировать машинный код. Результатом их работы были промежуточные исходники на Си. Это позволяло без особых усилий переносить языки на любую платформу, где есть стандартный компилятор Си.
В современных компиляторах сохранилось разделение на фронтенд, поддерживающий определённый язык программирования, и бэкенд, способный генерировать код для нужной платформы. Но для связи между ними Си, как правило, больше не нужен. Чтобы добавить поддержку языка, нужно разработать новый фронтенд. А заменой бэкенда можно добиться генерации кода для другой платформы.
Так устроен, в частности, популярный компилятор LLVM, фронтенды которого понимают большинство распространённых языков программирования. Результат работы фронтенда — байт-код для виртуальной машины, напоминающий ассемблер несуществующего RISC-процессора с бесконечным числом регистров и сильной типизацией данных. Бэкенды LLVM поддерживают, среди прочего, системы команд процессоров x86, ARM, MIPS, PowerPC и даже мейнфреймов IBM.
Бэкенд LLVM, способный генерировать Javascript вместо машинного кода x86 или ARM — настолько очевидная идея, что его появление было вопросом времени. Самый популярный проект такого рода был начат одним из инженеров Mozilla около пяти лет назад. Он называется Emscripten.
Emscripten
Emscripten представляет собой компилятор Си, Си++ и других языков, поддерживаемых LLVM, в Javascript, пригодный для исполнения в браузере. Этот проект также включает в себя реализацию распространённых библиотек для работы с трехмерной графикой, звуком и вводом-выводом на базе браузерных программных интерфейсов.
Тяжелее приходится с концепциями, которых в Javascript просто нет. Чтобы имитировать указатели и работу с памятью, тут идёт в ход та же уловка, что и в джаваскриптовых эмуляторах игровых приставок: программа создаёт типизированный массив, который играет роль динамически распределяемой памяти, и заменяет указатели на индексы элементов в этом массиве.
Код на Javascript непрерывно следит за тем, чтобы не покинуть отведённые массиву рамки, не выходить за пределы массивов, не переполнить стек. Это тратит уйму ресурсов, но даже с учётом всех накладных расходов программы, скомпилированные Emscripten, работали всего в несколько раз медленнее, чем те же исходники, скомпилированные в машинные коды. А в 2013 году у авторов проекта появилась возможность избавиться и от этих помех.
Asm.js
Недостающий компонент, который позволяет добиться максимальной скорости, называется asm.js. Спецификация asm.js задаёт упрощённое подмножество Javascript, которое может быть передано для исполнения более примитивному и потому очень быстрому интерпретатору. Оно идеально подходит в качестве промежуточного языка для таких генераторов кода, как Emscripten. Поддержка asm.js уже есть в браузерах Google, Mozilla и даже Microsoft.
Рассмотрим пример кода, написанного для asm.js:
Вот первое, что бросается в глаза: это обычный Javascript. Ему определённо не нужен ни специальный интерпретатор, ни предварительная обработка. Судя по всему, он заработает и без них. Не так быстро, как в интерпретаторе, знающем о существовании asm.js, но заработает.
Это не слишком удобно для человека, но нужно понимать, что asm.js — не для людей. Генератору кода всё равно, что генерировать, а интерпретатор, поддерживающий asm.js, понимает, что такая демонстративная конвертация — это вовсе не конвертация, а неуклюжая попытка задать тип переменной, и действует соответственно.
Что это даёт? Во-первых, интерпретатор и JIT-компилятор могут быть уверены, что внутри модуля тип переменных никогда не меняется. Больше не нужны постоянные проверки типа во время исполнения и принудительное приведение типов к общему знаменателю. Во-вторых, нет динамического выделения памяти и, соответственно, сборки мусора. Наконец, сама реализация объектов и организация памяти может быть более эффективной. Главное — поменьше рефлексии (и прочей динамики).
Всё это значительно повышает эффективность JIT-компиляции. Производительность кода, который выдают последние версии Emscripten, достигает 50-70 процентов от нативной скорости исполнения той же программы. Разработчики утверждают, что на устройствах, работающих под управлением Android, Javascript, который генерирует Emscripten, работает быстрее, чем Java.
Ограничения среды
Самые простые программы Emscripten просто перекомпилирует, не задавая лишних вопросов. Однако во многих случаях к переносу программы в браузер следует подходить так же, как к портированию на другую платформу (и ожидать похожих проблем). Любой код, который использует особенности определённой платформы или среды разработки, может стать серьёзным препятствием. От него придётся избавиться. Зависимость от библиотек, исходники которых недоступны, должна быть устранена. Не исключено, что в процессе портирования проявят себя ошибки, которых прежде удавалось избежать — другая среда исполнения и другой оптимизатор часто имеют такой эффект.
Кроме того, остаётся ещё одна важная деталь: программы, которые рассчитаны на работу в течение продолжительного времени, как правило, крутятся в цикле — они ждут поступления событий из внешнего мира и реагируют на них. Так продолжается, пока их не выключат. Браузер и, соответственно, программы на Javascript устроены совершенно иначе.
В браузере этот цикл реализован на другом, более высоком уровне, чем пользовательская программа. Он позволяет назначить функции на Javascript, которые должны быть вызваны в случае определённого события, но вызывает их сам и ожидает, что они быстро отработают своё и вернут управление. Они не должны работать долго.
Любая программа на Javascript, которая не только реагирует на события DOM, но и делает нечто большее, быстро упирается в это ограничение. Лазейки, которые позволяют его обойти, тоже давно известны. Джаваскриптовые эмуляторы игровых консолей, о которых рассказывалось в статье «Байт из других миров. Как ретрокомпьютеры эмулируют на Javascript», привязывают исполнение каждого такта виртуального процессора к таймеру. В этом случае каждый виток внутреннего цикла эмулятора активирует сам браузер.
Если в программе несколько подобных циклов, и она может переходить из одного в другой по собственному желанию, потребуется более значительная переработка кода. Дело в том, что задать функцию внутреннего цикла при помощи emscripten_set_main_loop можно лишь один раз. Придется собрать все внутренние циклы в одну функцию и всякий раз проверять, в каком именно цикле мы находимся.
Жертва значительна, но не смертельна. Emterpreter sync используется, в частности, в Em-DOSBox, браузерной версии известного эмулятора MS-DOS. Потерянная производительность не мешает этой программе успешно воспроизводить множество компьютерных игр для PC, написанных в девяностые годы, и даже Windows 95.
Profit
Сфера применения EmScripten не ограничивается эмуляторами и старинными игрушками (помимо DOSBox, на Emscripten перенесли Doom, Quake 3, Dune 2 и ScummVM, виртуальную машину для классических квестов LucasArts и Sierra). Попытки запустить в браузере такие популярные скриптовые языки, как Python, Ruby и Lua, тоже увенчались успехом, хотя их практичость остается сомнительной. Каждый из них требует загрузки многомегабайтного рантайма; для обычного сайта это неприемлемо.
Видеокодеки, просмотрщики PDF, SQLite и система распознавания речи — это уже интереснее. Наконец, нельзя не упомянуть, что существует проект переноса в браузер браузерного движка Webkit. Это не утка: он работает, в том числе внутри Webkit. Трудно подобрать эпитет, в полной мере описывающий характер этого достижения, но с тем, что это достижение, не станет спорить никто.
Если даже после этого (особенно после этого) вы ещё не оценили всю серьёзность происходящего, остаётся добавить, что Emscripten поддержали компании Epic Games и Unity Technologies. Первая портировала на Javascript популярнейший игровой движок Unreal Engine. Он настолько популярен, что проще перечислить игры, где его нет. Другая с помощью Emscripten разработала джаваскриптовую версию Unity 3D. С такой поддержкой эта технология определённо пойдёт далеко.
Сделано в Emscripten
Angry Bots
Старые игры
Не так давно Internet Archive выложил на всеобщее обозрение огромное количество старинных игр для всех возможных платформ, начиная со Spacewar образца 1962 года (считается, что это первая компьютерная игра) и заканчивая, извините, Flappy Bird. Между ними есть всё, что можно придумать. За воспроизведение отвечает джаваскриптовый порт эмулятора MESS/MAME, который поддерживает без малого тысячу исторических игровых платформ.
Интерпретаторы языков программирования
Интерпретатор Scheme
На этой странице выложены интерпретаторы Python, Ruby, Scheme, Lua, Java, QBasic, Forth и множества других языков программирования. Для ценителей есть даже Brainfuck. С каждым можно поиграться прямо в браузере, сохранить введённый код и поделиться им со знакомыми в Facebook и Twitter. Знакомые оценят — особенно, если это Brainfuck.
Dead Trigger 2
Ещё одна демка Unity 3D. В Dead Trigger 2, вместо псевдоизометрии Angry Bots, мы имеем вид от первого лица и большой окровавленный топор. Низкополигональная местность, напоминающая задворки оптового рынка на окраине Москвы, не радует, но Emscripten в этом вряд ли виноват. Виноваты зомби, которые сделали эту игру.
Tappy Chicken
Epic Games, демонстрируя джаваскриптовую версию Unreal Engine 3, пытается впечатлить не публику, а разработчиков. Публике тут смотреть не на что: это клон Flappy Bird с сельскохозяйственным уклоном. Программистов же может впечатлить тот факт, что эта курица без особых проблем конвертируется не только в Javascript, но и в приложения для iOS и Android. Не всех программистов, конечно. Только самых впечатлительных.
«Дум» даже в DOSBox, переведённом на Javascript, остаётся «Думом». Двадцать лет почти не изменили его (монстры выглядят странно, но, вероятно, не из-за Emscripten, а из-за копирайта), только пиксели стали крупнее. Думал ли Кармак, что его передовую игру будут портировать на каждую платформу, одну другой меньше? Вряд ли. Quake 3 на Javascript, кстати, тоже есть.
Да, это классический текстовый редактор. Он работает не хуже обычного. Нет, я не знаю, как сохранять файлы.