JS из Haxe
Nov. 13th, 2014 02:58 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
В продолжение бенчмарка с декодированием картинки в браузере. Сделал генерацию 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 доводит!
Обновленная сводка:
Время декодирования одной конкретной картинки 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 доводит!
no subject
Date: 2014-11-12 08:34 pm (UTC)no subject
Date: 2014-11-13 06:04 am (UTC)no subject
Date: 2014-11-12 08:55 pm (UTC)no subject
Date: 2014-11-13 04:05 am (UTC)no subject
Date: 2014-11-13 12:42 am (UTC)доступна, только не в Dartiumе :(
странный подход. не понятно, почему не делают просто
x >>> 0
.dart2js, как раз и делает вывод типов, только глобальный и с анализом потока выполнения --- был бы Dart статически типизированный как Haxe - компилировался бы быстрее. dart2js же вообще на аннотации типов не смотрит - он смотрит только на код и что он делает, а потом пытается понять какие типы значений куда попадают.
Плюс ему надо прожевать все библиотеки, которые ты импортируешь - а это больше, чем 300 строк кода.
Но вообще 10сек это, конечно, стыдоба понятное дело, что я оправдываюсь :)
Прогретый dart2js в batch режиме быстрее работает - но все равно не 0.15c. В любом случае Edit&Refresh cycle в Dart не предполагает постоянную компиляцию (как раз потому что Dartium есть)... в пределах 0.15c будет только икрементальный режим dart2js показывать - но там код в результате будет не быстрый отнюдь.
no subject
Date: 2014-11-13 04:01 am (UTC)>dart2js, как раз и делает вывод типов, только глобальный и с анализом потока выполнения --- был бы Dart статически типизированный как Haxe - компилировался бы быстрее. dart2js же вообще на аннотации типов не смотрит - он смотрит только на код и что он делает, а потом пытается понять какие типы значений куда попадают.
Хм, а ты точно не про ВМ? На аннотации он смотрит, т.к. ворнингами несоответствие оным выдает. А про Dynamic это и редактор показывает в inferred type, и в доках сказано:
"You might notice when you’re debugging your code that variables with no specified type get a special type: dynamic."
Впрочем, весь этот подход с его optional typing какой-то странный. Тут указываем, тут проверяем, тут выкидываем и не смотрим, тут выводим с нуля, тут определяем в рантайме... Подход Haxe и C#, с явными dynamic где они нужны и статическими типами в других местах, выглядит и понятней, и эффективней.
Библиотеки импортируются и там, и там, примерно одни и те же.
no subject
Date: 2014-11-13 08:37 am (UTC)Я тебе ее исключительно для локальных замеров предлагал.
Ну да, я не очень точно выразился: он не смотрит на типы для целей кодогенерации. На типы для показа warnings он смотрит.
Он странный до тех пор пока ты его пытаешься воспринимать как статически типизированный, потому что возникает когнитивный диссонанс.
Надо воспринимать Dart как обычный такой, динамически типизированный Smalltalk с C-синтаксисом - и тогда диссонанс пропадает. Таким уж его создали создатели :)
no subject
Date: 2014-11-13 10:07 am (UTC)no subject
Date: 2014-11-13 09:09 pm (UTC)Может там в процессе допиливания UINT соптимизировалось что-то
no subject
Date: 2014-11-15 04:35 pm (UTC)no subject
Date: 2014-11-16 05:01 am (UTC)