JS из Haxe
Nov. 13th, 2014 02:58 amВ продолжение бенчмарка с декодированием картинки в браузере. Сделал генерацию 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 доводит!