thedeemon: (office)
Ну что ж, друзья мои, по крайней мере в Firefox'e для числодробилок в браузере нет языка лучше, чем С++. Но только там, правда.

Задействовал сегодня Emscripten :: С++ -{clang/LLVM}-> ASM.js.
Чтобы его поставить уж было расчехлил свой линукс, но оказалось, что проще всего его поставить как раз в винде: установка в один клик, и все сразу работает из коробки. Использовать С++ код из JS оказалось весьма просто, когда разберешься что к чему. Ключевой момент: ASM.js работает в пределах одного единственного массива фиксированной длины. Просто так передать ему пару других массивов из JS не выйдет, нужно выделять для них память в этой вот куче ASM.js, копировать туда, потом оттудова читать результат. В Firefox'e компиляцией ASM.js кода занимается отдельный специализированный ahead of time конпелятор, в то время как остальные браузеры относятся к нему как к обычному JS.

В итоге на тесте с декодированием картинки на моем ноуте текущая ситуация такая (время декодирования в миллисекундах и размер кода):
             Chrome 38:     Firefox 33:    IE 11:       Size:

Flash           57              58           58          6 KB
Dart to JS      60              70           95        135 KB
C++  to ASM.js  54              43          149        212 KB
Haxe to JS      52              49          fail        12 KB


Погонять ASM.js. Все тесты.

Успел даже на малюсеньком тесте столкнуться с разницей браузеров в исполнении/неисполнении JS: что работало в Хроме, падало в Firefox'e: он видите ли не дает responseType у XHR устанавливать до вызова open(). А сгенеренный Haxe'ом код не взлетел в IE: не могу, говорит, скастить HTMLInputElement в HTMLInputElement (хвала динамической типизации, где сравнение типов может делать что угодно кроме того, что надо!).

Итого, если ориентироваться на Firefox, то рулит С++ и ASM.js, в Хроме рулит чистый JS (который фактически и получается из Haxe), а если нужно, чтобы был компактный код, который стабильно и шустро работает везде, то по-прежнему рулит Flash. Ну а если еще про айфоны всякие вспомнить, то... проще плюнуть и никогда больше к этому проклятому болоту, фронтэнду, не приближаться.
thedeemon: (office)
В продолжение бенчмарка с декодированием картинки в браузере. Сделал генерацию JS из Haxe (погонять тест). Получилось обогнать Flash!

Обновленная сводка:
Время декодирования одной конкретной картинки 960х540 на ноуте с Core i3:
Native C++ (старинный интеловский компилятор): 34 ms
JS, сгенеренный из Haxe, в Chrome 38: 52 ms в винде и 50 ms в линуксе в Chromium 31.
Flash, скомпиленный из Haxe: 57 ms (updated) в винде и 55 ms в линуксе.
JS, сгенеренный из Dart, в Chrome 38: 60 ms
JS, сгенеренный из Dart, в Chrome 37: 62 ms
Тот же JS в IE 11: 95 ms
Dart на Dart VM: 172 ms

Про Dart VM авторитетный источник mr_aleph сообщил, что тормоза из-за интов, не влезающих в 31 бит, и что на 64-битной Dart VM все сильно шустрее JS, но простым смертным под виндой она пока недоступна, как я понял.

Однако с Haxe->JS пришлось помучиться больше всех. Получить работающий вариант, имея рабочую версию на Haxe для Flash'a, было несложно - заменил API, и главное - массивы, со флешеспецифичных на JS-специфичные (вроде Int32Array, обычные типизированные массивы и вектора Haxe превращаются в простой Array в JS почему-то). Но такой вариант тратил на кадр более 170 мс - прям как ДартВМ. И опять загвоздка была в UInt'aх. У меня оригинальный код на С++ оперировал 32-битными беззнаковыми интами, там это естественно и быстро. На флеше с этим тоже никаких проблем. В Дарте один целый тип - int - и он достаточно вместительный, чтобы без раздумий работать со значениями от 0 до 0xFFFFFFFF, тоже ок. Но если я использую в Haxe UInt (который исходно 32-битный беззнаковый), то при трансляции в JS битовые операции с ним работают как со знаковым 32-битным интом, и, например, 0xFF00 << 16 это отрицательное число там. Чтобы программа работала как задумано, Haxe там, где UInt должен вести себя соответственно, делает сравнение его с 0 и прибавление 4294967296.0 для получения положительного значения. А банальное сравнение с положительной константой превращается вообще в черти-что с вызовом лямбды по месту зачем-то. Вот все это и тормозит. Причем если заменить UInt на Int, то Haxe плюет на его разрядность, и код выглядит уже просто и без лишних сравнений и сложений, и в принципе позволяет иметь положительные числа вроде 0xFFFFFFFF, как мне надо, но любая битовая операция делает их отрицательными. Лишь избавившись от таких операций там, где они вредили, получилось получить работающий и быстрый код. Который выглядит очень похоже на оригинал на Haxe (размер правда вырос с 6 до 12 КБ).
А все это ужасное говно JS c его чудо-семантикой. Посмотрим, что покажет Emscripten...

А, еще момент. На этом моем проектике в три сотни строк dart2js потеет 10 секунд. Транслятор Haxe (написанный на Окамле) отрабатывает за 0.15 с. При том, что там честный вывод типов, а не втыкание Dynamic везде, где не указано обратного.
А редактор егойный, FlashDevelop, ест памяти обычно раз в 20 меньше, чем DartEditor (30 мегов вместо 600). Вот до чего людей Java доводит!
thedeemon: (office)
Занялся тут изучением вариантов по переносу своего кодека в браузер. На Flash'e у меня уже был декодер, но это нынче не модно. Решил посмотреть разные другие способы, сравнив сперва их скорость на небольшой части кодека, наиболее времязанимающей, - декодировании ключевого кадра в RGB24. Там много массивов, циклов и простой целочисленной арифметики. Стали появляться первые результаты, порой довольно неожиданные. Dart VM, которую позиционируют как более продвинутую и быструю, оказалась втрое медленнее джаваскрипта (в Хроме), сгенеренного из того же самого дартовского исходника штатной утилитой dart2js. JS в Хроме лишь немного медленее чем Flash, и оба в пределах 2x от нативного кода на С++.

Время декодирования одной конкретной картинки 960х540:
На ноуте с Core i3:
Native C++ (старинный интеловский компилятор): 34 ms
Flash (compiled from Haxe): 58 ms
Dart на DartVM: 172 ms
JS, сгенеренный из Dart, в Chrome 37: 62 ms
Тот же JS в IE 11: 95 ms

На простеньком андроидном планшете:
Тот же JS в Chrome 34: 379 ms
Он же в дефолтном браузере там: 971 ms

На стареньком андроидном телефоне:
JS в дефолтном браузере: не взлетел
JS в Firefox: 976 ms
Flash: 472 ms

Тесты можно погонять тут:
JS (generated from Dart)
Flash (compiled from Haxe)
Dart (работает лишь в Dartium)

О размерах:
Flash распространяется скопилированным в байткод, .swf файл: 6 KБ
Dart, распространяется в исходнике: 9 КБ
Сгенеренный из него JS: 135 КБ при включенной минификации, более 300 КБ без оной.
Т.е. хвалебные рассказы про деревотрясение и оптимизацию... для небольших программ неактуальны, dart2js пихает туда довольно толстый рантайм. А еще каждое обращение к элементу массива в сгенеренном коде сопровождается ручной проверкой на выход за пределы с вызовом какой-то дартоспецифичной функции в случае ошибки. Я не знаю, насколько хорошо JS движки это оптимизируют, выглядит как куча ненужной работы.

Буду продолжать наблюдения. В планах еще как минимум генерация JS из Haxe и генерация ASM.js из С++. Писать на самом JS вы меня не заставите. :)

Profile

thedeemon: (Default)
Dmitry Popov

September 2017

S M T W T F S
     12
3456789
10111213141516
17181920212223
24252627282930

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 26th, 2017 07:15 am
Powered by Dreamwidth Studios