
Haxe vs Flash: Как не надо делать тесты производительности
Обновления в конце
Вводные: задача не выжать миллион fps, а заставить при равных условиях не проиграть хаксу
Сразу хочу сказать, что я в Haxe полный ноль. Парочку файлов собрал относительно недавно. За день до этого у меня была истерическая беседа с одним человеком, который работает с Haxe. Не буду выдавать все детали. Кто знает — молодец. Кто не знает — ничего не потерял. После общения с ним мне стало любопытно. А почему ХаКс всё же шустрее работает? Начал ковырять его вдоль и поперек и нануглил интересную страничку adobe.ly/15IZlJu, где человек собрал еще в 2009 году простой пример, показывающий FPS проекта на флеше и на ХаКсе.
Речь пойдет не о том, кто лучше или хуже. Я хочу показать пример как не надо проводить тесты, т.к. многие люди в них верят.
Первое, что нам надо — скачать исходники adobe.ly/15ajTbA и извлечь их. Там лежат файлы для хакса и Flash IDE и так же готовые swf'ки с html'ками
Запускаем mandelbrot-as3.html и смотрим на генерацию фракталов. У меня заняла ~538мс первичная генерация. FPS стабильно 143.

Теперь запустим mandelbrot-haxe.html, который собрал Haxe. Генерация ~213мм и FPS 250. Всё, думаю. Приехали. Но решил поковырять — что же такого ХаКс делает, что имеет львиную мощность.

Запускаем Fla файлик и смотрим код проекта (он зачем-то в кадре):

Первым непониманием стала конструкция:
Тут первая ошибка — в постоянном обращении к stage для получения stageWidth и stageHeight. Кто не совсем понимает что это значит — приведу код:
Т.е. мы постоянно заставляем Flash плеер обращаться к своим низкоуровневым методам для получения размера стейжда и вываливаем его в AS3.
Сделаем банальные изменения — закешируем значения

и запустим mandelbrot-as3.html для проверки эффективности внесенных изменений.

Замечательно — 143fps превратились в 200. Все ли меня устраивает? Нет! Почему-то Haxe версия быстрее генерирует фракталы и быстрее их рисует.
Смотрим код дальше и начинаем обращать внимание на отсутстие типизации у pixel и других переменных. Теперь надо запилить правильную типизацию. Ведь без этого затратно работать с переменными. За одно массив под пиксели переведем в вектор (8 строка на картинке). Попутно все обращения к stage.stageWidth/stage.stageHeight мы закешируем с помощью одних и тех же переменных.
В итоге получаем такой код:

Запускаем его и получаем:

250 fps и ~100ms генерация фракталов. Вроде как бы и не плохо. Но что-то мне хочется больше. Хотя, согласитесь, что с 143 fps ~538ms уже разница большая. Что делаем дальше? А вот, что! Смотрим swf из Haxe декомпилятором и видим, что там обновление вызывается таймер без получения TimerEvent. А значит не может быть там таймера. И я оказываюсь прав — там setInterval используется.

Перепиливаем код под setInterval с Timer:

Собираем и видим, что 250fps теперь у нас мечется между 250 и 300 с копейками. Быстро дергается. Но не всё время. Пока меня не сильно устраивает ~100ms генерация фракталов. Что-то с этим надо делать.
Превым делом убираем ущербный код в кадре и выносим в отдельный класс и малось вносим в него правки (for меняем на while). На выходе имеем такой класс:
Запускаем его и видим результат работы:

Тестировалось на железе процессоре i7 4770. Будет интересно услышать Ваши тесты.
1. Не оптимизированные оригинальный файл автора gametrax.eu/game/3cc2563012
2. Мой оптимизированный файл gametrax.eu/game/2c87821847
3. Оригинал swf из haxe gametrax.eu/game/a3911fde86
Для удобочитаемости прошу ответить по шаблону, чтоб легче читать было:
Проц: i7 4770
1. 532ms @ 143fps
2. 81ms @ 250fps
3. 213ms @ 250fps
P.S. Т.к. в Haxe я не силен — дождусь человека, который сможет поправить хаксовский исходник для добавления 4й опции по тестированию быстродействия.
Резюмирую:
Если кто-либо будет проводить тесты на сторонних сайтах — не надейтесь, что они будут выжимать 100% из Flash Player. Доверяйте лишь своему опыту.
Позже я хочу попытаться разобраться в байткоде из haxe и понять что там такого магического… Быть может получится собрать какой-либо патчер для флешек :)
Обновление #1
— Теперь ролики имеют 640х480х60fps параметры (было 320х240)
— Обновленный 2й ролик более оптимизирован, чем в предыдущей версии
— 3й Ролик из Хакса рефакторенный моими руками (не нарю в хаксе, но получилось) + оптимизация в соответствии с копией во флеш
— Во 2м и 3м ролике добавлен счетчик максимального FPS, который был получен
— Обновление интервала сокращено до 5мс (было 10)
1. Не оптимизированный оригинальный файл автора gametrax.eu/game/0fd6ee87b7 (не изменялся код, изменил просто байты ширины и высоты ролика, чтоб соответстовать новым размерам)
2. Дополнительная оптимизация gametrax.eu/game/58327776bf
3. Обновленный Haxe gametrax.eu/game/6388c03c11
1. 2265ms @ 34fsp
2. 259ms @ 63fps ( max 67fps)
3. 266ms @ 67fps (max 67fps)
Исходник обновленного AS3 проекта:
Исходник обновленного Haxe:
Обновление #2
Всё! Победил я Haxe этот!
1) as3 + кунг-фу gametrax.eu/game/9461a62e7c
2) haxe gametrax.eu/game/071e94de01
Надеюсь ничего не напутал…
Из 63 fps на ас3 получили 77 простым телодвижением, как оказалось. Ну, не совсем простым. Но телодвижением :)
Короче, есть такой опкод add, который из стека вытягивает два значения и суммирует их. Но сначала типизирует. Так вот, в коде были строки pixel + colorModifier + r и прочие, которые складывались через add.
заменил add на add_i везде, где суммировались integer и это снесло мне шаблон.
плюс изменил немного инструкции по коду (влом уже проверять дало что-то или нет)…
Прошу глянуть 1 и 2 и отписаться fps и max fps
Вводные: задача не выжать миллион fps, а заставить при равных условиях не проиграть хаксу
Сразу хочу сказать, что я в Haxe полный ноль. Парочку файлов собрал относительно недавно. За день до этого у меня была истерическая беседа с одним человеком, который работает с Haxe. Не буду выдавать все детали. Кто знает — молодец. Кто не знает — ничего не потерял. После общения с ним мне стало любопытно. А почему ХаКс всё же шустрее работает? Начал ковырять его вдоль и поперек и нануглил интересную страничку adobe.ly/15IZlJu, где человек собрал еще в 2009 году простой пример, показывающий FPS проекта на флеше и на ХаКсе.
Речь пойдет не о том, кто лучше или хуже. Я хочу показать пример как не надо проводить тесты, т.к. многие люди в них верят.
Первое, что нам надо — скачать исходники adobe.ly/15ajTbA и извлечь их. Там лежат файлы для хакса и Flash IDE и так же готовые swf'ки с html'ками
Запускаем mandelbrot-as3.html и смотрим на генерацию фракталов. У меня заняла ~538мс первичная генерация. FPS стабильно 143.

Теперь запустим mandelbrot-haxe.html, который собрал Haxe. Генерация ~213мм и FPS 250. Всё, думаю. Приехали. Но решил поковырять — что же такого ХаКс делает, что имеет львиную мощность.

Запускаем Fla файлик и смотрим код проекта (он зачем-то в кадре):

Первым непониманием стала конструкция:
for(ix=0; ix<stage.stageWidth; ix++) {
for(iy=0; iy<stage.stageHeight; iy++) {
Тут первая ошибка — в постоянном обращении к stage для получения stageWidth и stageHeight. Кто не совсем понимает что это значит — приведу код:
public function get stageWidth () :int{
/* Тут идет нативный код считывания размеров Stage */
return value;
}
Т.е. мы постоянно заставляем Flash плеер обращаться к своим низкоуровневым методам для получения размера стейжда и вываливаем его в AS3.
Сделаем банальные изменения — закешируем значения

и запустим mandelbrot-as3.html для проверки эффективности внесенных изменений.

Замечательно — 143fps превратились в 200. Все ли меня устраивает? Нет! Почему-то Haxe версия быстрее генерирует фракталы и быстрее их рисует.
Смотрим код дальше и начинаем обращать внимание на отсутстие типизации у pixel и других переменных. Теперь надо запилить правильную типизацию. Ведь без этого затратно работать с переменными. За одно массив под пиксели переведем в вектор (8 строка на картинке). Попутно все обращения к stage.stageWidth/stage.stageHeight мы закешируем с помощью одних и тех же переменных.
В итоге получаем такой код:

Запускаем его и получаем:

250 fps и ~100ms генерация фракталов. Вроде как бы и не плохо. Но что-то мне хочется больше. Хотя, согласитесь, что с 143 fps ~538ms уже разница большая. Что делаем дальше? А вот, что! Смотрим swf из Haxe декомпилятором и видим, что там обновление вызывается таймер без получения TimerEvent. А значит не может быть там таймера. И я оказываюсь прав — там setInterval используется.

Перепиливаем код под setInterval с Timer:

Собираем и видим, что 250fps теперь у нас мечется между 250 и 300 с копейками. Быстро дергается. Но не всё время. Пока меня не сильно устраивает ~100ms генерация фракталов. Что-то с этим надо делать.
Превым делом убираем ущербный код в кадре и выносим в отдельный класс и малось вносим в него правки (for меняем на while). На выходе имеем такой класс:
package {
import flash.display.Sprite;
import flash.utils.getTimer;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.text.TextField;
import flash.utils.setInterval;
import flash.utils.setTimeout;
public class Main extends Sprite {
private var _stage_width: int;
private var _stage_height: int;
private var bitmapData: BitmapData;
private var colorModifier: int = 2;
private var pixel: uint = 0x000000;
private var pixels: Vector.<Vector.<int>>;
private var fps: TextField;
private var ix: int = 0;
private var iy: int = 0;
public function Main() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e: Event): void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
_stage_width = stage.stageWidth;
_stage_height = stage.stageHeight;
var setBitmap: Bitmap = new Bitmap();
bitmapData = new BitmapData(_stage_width, _stage_height, false, 0x000000);
setBitmap.bitmapData = bitmapData;
addChild(setBitmap);
pixels = new Vector.<Vector.<int>>(2);
var maxIterations: int = 128;
var beforeTime = getTimer();
var xtemp: Number = 0;
var x0: Number = 0;
var y0: Number = 0;
var iteration = 128;
var ix:int =0;
var iy:int =0;
while ( ix < _stage_width){
pixels[ix] = new Vector.<int>(_stage_width,true);
iy = 0;
while ( iy < _stage_height){
x0 = 0;
y0 = 0;
iteration = 128;
while (x0 * x0 + y0 * y0 <= 4 && iteration > 0) {
xtemp = x0 * x0 - y0 * y0 + (ix - 14 * 5000) / 50000;
y0 = 2 * x0 * y0 + (iy - (_stage_height / 0.6)) / 50000;
x0 = xtemp;
iteration--;
}
pixels[ix][iy] = iteration;
iy ++;
}
ix++;
}
var afterTime = getTimer();
var tf = new TextField();
tf.width = 400;
tf.text = "Generating fractal took " + (afterTime - beforeTime) + " ms";
addChild(tf);
fps = new TextField();
fps.width = 400;
fps.y = 10;
fps.text = "FPS: ";
addChild(fps);
setInterval(update, 10);
}
private function update(): void {
var r: int = 0;
var b: int = 0;
var g: int = 0;
var beforeTime = getTimer();
ix = 0;
while (ix<_stage_width){
iy =0;
while(iy<_stage_height){
pixel = pixels[ix][iy];
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
bitmapData.setPixel(ix, iy, (r << 16 | g << 8 | b));
iy++;
}
ix++;
}
var afterTime = getTimer();
fps.text = "FPS: " + Math.round(1000 / (afterTime - beforeTime));
colorModifier += 2;
if (colorModifier > 65530)
colorModifier = 0;
}
}
}
Запускаем его и видим результат работы:

Тестировалось на железе процессоре i7 4770. Будет интересно услышать Ваши тесты.
1. Не оптимизированные оригинальный файл автора gametrax.eu/game/3cc2563012
2. Мой оптимизированный файл gametrax.eu/game/2c87821847
3. Оригинал swf из haxe gametrax.eu/game/a3911fde86
Для удобочитаемости прошу ответить по шаблону, чтоб легче читать было:
Проц: i7 4770
1. 532ms @ 143fps
2. 81ms @ 250fps
3. 213ms @ 250fps
P.S. Т.к. в Haxe я не силен — дождусь человека, который сможет поправить хаксовский исходник для добавления 4й опции по тестированию быстродействия.
Резюмирую:
Если кто-либо будет проводить тесты на сторонних сайтах — не надейтесь, что они будут выжимать 100% из Flash Player. Доверяйте лишь своему опыту.
Позже я хочу попытаться разобраться в байткоде из haxe и понять что там такого магического… Быть может получится собрать какой-либо патчер для флешек :)
Обновление #1
— Теперь ролики имеют 640х480х60fps параметры (было 320х240)
— Обновленный 2й ролик более оптимизирован, чем в предыдущей версии
— 3й Ролик из Хакса рефакторенный моими руками (не нарю в хаксе, но получилось) + оптимизация в соответствии с копией во флеш
— Во 2м и 3м ролике добавлен счетчик максимального FPS, который был получен
— Обновление интервала сокращено до 5мс (было 10)
1. Не оптимизированный оригинальный файл автора gametrax.eu/game/0fd6ee87b7 (не изменялся код, изменил просто байты ширины и высоты ролика, чтоб соответстовать новым размерам)
2. Дополнительная оптимизация gametrax.eu/game/58327776bf
3. Обновленный Haxe gametrax.eu/game/6388c03c11
1. 2265ms @ 34fsp
2. 259ms @ 63fps ( max 67fps)
3. 266ms @ 67fps (max 67fps)
Исходник обновленного AS3 проекта:
package {
import flash.display.Sprite;
import flash.utils.getTimer;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.text.TextField;
import flash.utils.setInterval;
import flash.utils.setTimeout;
public class Main extends Sprite {
private var _stage_width: int;
private var _stage_height: int;
private var bitmapData: BitmapData;
private var colorModifier: int = 2;
private var pixel: uint = 0;
private var pixels: Vector.<Vector.<int>>;
private var fps: TextField;
private var maxFPS : int = 0;
private var curFPS : int = 0;
public function Main() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e: Event): void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
_stage_width = stage.stageWidth;
_stage_height = stage.stageHeight;
var setBitmap: Bitmap = new Bitmap();
bitmapData = new BitmapData(_stage_width, _stage_height, false, 0x000000);
setBitmap.bitmapData = bitmapData;
addChild(setBitmap);
pixels = new Vector.<Vector.<int>>(2);
var maxIterations: int = 128;
var beforeTime = getTimer();
var xtemp: Number = 0;
var iteration : int = 128;
var ix:int =0;
var iy:int =0;
var x0:Number = 0.0;
var y0:Number = 0.0;
while ( ix < _stage_width){
pixels[ix] = new Vector.<int>(_stage_width,true);
iy = 0;
while ( iy < _stage_height){
x0 = 0;
y0 = 0;
iteration = 128;
while (x0 * x0 + y0 * y0 <= 4 && iteration > 0) {
xtemp = x0 * x0 - y0 * y0 + (ix - 70000) / 50000;
y0 = 2 * x0 * y0 + (iy - (_stage_height / 0.6)) / 50000;
x0 = xtemp;
iteration--;
}
pixels[ix][iy] = iteration;
iy ++;
}
ix++;
}
var afterTime = getTimer();
var tf = new TextField();
tf.width = 400;
tf.text = "Generating fractal took " + (afterTime - beforeTime) + " ms";
addChild(tf);
fps = new TextField();
fps.width = 400;
fps.y = 10;
fps.text = "FPS: ";
addChild(fps);
setInterval(update, 5);
}
private function update(): void {
var r: int = 0;
var b: int = 0;
var g: int = 0;
var beforeTime : int = getTimer();
var ix :int = 0;
while (ix<_stage_width){
var iy :int =0;
while(iy<_stage_height){
pixel = pixels[ix][iy];
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
bitmapData.setPixel(ix, iy, (r << 16 | g << 8 | b));
iy++;
}
ix++;
}
curFPS = Math.round(1000 / ( getTimer() - beforeTime));
if ( curFPS > maxFPS ){
maxFPS = curFPS;
}
fps.text = "FPS: " + curFPS + "\rMax FPS: " + maxFPS;
colorModifier += 2;
if (colorModifier > 65530)
colorModifier = 0;
}
}
}
Исходник обновленного Haxe:
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.text.TextField;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
class Mandelbrot
{
static function main() : Void
{
new Mandelbrot();
}
public var pixels:Array<Array<Int>>;
public var colorModifier:Int;
private var bitmapData:BitmapData;
private var fps:TextField;
public var sW:Int;
public var sH:Int;
public var maxFPS:Int;
public var curFPS:Int;
public function new()
{
sW = flash.Lib.current.stage.stageWidth;
sH = flash.Lib.current.stage.stageHeight;
var setBitmap:Bitmap = new Bitmap();
bitmapData = new BitmapData( flash.Lib.current.stage.stageWidth , flash.Lib.current.stage.stageHeight , false , 0x000000 );
setBitmap.bitmapData = bitmapData;
flash.Lib.current.addChild( setBitmap );
var maxIterations:Int = 128;
pixels = new Array<Array<Int>>();
var beforeTime = flash.Lib.getTimer();
var xtemp:Float;
var iteration:Int;
var x0:Float = 0;
var y0:Float = 0;
for(ix in 0...sW) {
pixels[ix] = new Array<Int>();
for(iy in 0...sH) {
x0 = 0;
y0 = 0;
iteration = 128;
while ( x0*x0 + y0*y0 <= 4 && iteration > 0 )
{
xtemp = x0*x0 - y0*y0 + (ix-14*5000)/50000;
y0 = 2*x0*y0 + (iy-(sH/0.6))/50000;
x0 = xtemp;
iteration--;
}
pixels[ix][iy] = iteration;
}
}
var afterTime = flash.Lib.getTimer();
var tf = new TextField();
tf.width = 400;
tf.text = "Generating fractal took "+(afterTime-beforeTime)+" ms";
flash.Lib.current.addChild(tf);
fps = new TextField();
fps.width = 400;
fps.y = 10;
fps.text = "FPS: ";
flash.Lib.current.addChild(fps);
colorModifier = 2;
var timer:haxe.Timer = new haxe.Timer(5);
runLoop();
timer.run = runLoop;
}
public function runLoop() {
var r:Int=0, b:Int=0, g:Int=0;
var pixel:Int = 0;
var beforeTime = flash.Lib.getTimer();
for(ix in 0...sW) {
for(iy in 0...sH) {
pixel = pixels[ix][iy];
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
bitmapData.setPixel(ix, iy, (r<<16 | g<<8 | b));
}
}
var afterTime = flash.Lib.getTimer();
curFPS = Math.round(1000/(afterTime-beforeTime));
if ( curFPS > maxFPS ){
maxFPS = curFPS;
}
fps.text = "FPS: " + curFPS + "\rMax FPS: " + maxFPS;
colorModifier += 2;
if(colorModifier > 65530)
colorModifier = 0;
}
}
Обновление #2
Всё! Победил я Haxe этот!
1) as3 + кунг-фу gametrax.eu/game/9461a62e7c
2) haxe gametrax.eu/game/071e94de01
Надеюсь ничего не напутал…
Из 63 fps на ас3 получили 77 простым телодвижением, как оказалось. Ну, не совсем простым. Но телодвижением :)
Короче, есть такой опкод add, который из стека вытягивает два значения и суммирует их. Но сначала типизирует. Так вот, в коде были строки pixel + colorModifier + r и прочие, которые складывались через add.
заменил add на add_i везде, где суммировались integer и это снесло мне шаблон.
плюс изменил немного инструкции по коду (влом уже проверять дало что-то или нет)…
Прошу глянуть 1 и 2 и отписаться fps и max fps
- +15
- TheRabbit
Комментарии (92)
120 200
269 200
i7-3630QM
Тогда тесты должны делать 2 человека, в формате соревнования, где цель сделать программу быстрее чем у оппонента, конечно с условиям приблизительно равных сил))
2. 233ms @ 145fps
3. 675ms @ 200fps
Проц: Core i3 CPU 550 @ 3200GHz
1) 12,416 ms @ 8 fps
2) 1,049 ms @ 22 fps
3) 4,320 ms @ 21 fps
2) 265 @ 71
3) 1209 @ 71
Я отдельно для себя делал версию 1920х1080 — флеш на 1 fps выдавал в итоге больше. При том, что я всунул кеширование в хаксовский пример (тоже отдельно). Не поленился старый ноут включил — что хакс версия, что флеш — выдают одинаковые fps. Правда флеш еще в 2.5 раза быстрее рисует фрактал изначально. Хочу, чтоб этот пример опытный хаксер оптимизировал :) Хочу другой тест.
1) 1033 ms @ 71 fps
2) 157 ms @ 143 fps
3) 421 ms @ 143 fps
4). И мой оптимизированный тест: 120 ms @ 143 fps
http://gametrax.eu/game/65c533a11b
Но немного оптимизировать можно, я думаю, в обоих вариантах.
1. Не оптимизированный оригинальный файл автора gametrax.eu/game/0fd6ee87b7 (не изменялся код, изменил просто байты ширины и высоты ролика, чтоб соответстовать новым размерам)
2. Дополнительная оптимизация gametrax.eu/game/58327776bf
3. Обновленный Haxe gametrax.eu/game/6388c03c11
1. 2265ms @ 34fsp
2. 259ms @ 63fps ( max 67fps)
3. 266ms @ 67fps (max 67fps)
i7 4770 :)
Собственно, не haxe vs flash меряю
Сколько показывает? Мерялка одинаковая.
Generating fractal took 257 ms
FPS: 1000, dt=1
Max FPS: 1000
1200*800
Generating fractal took 588 ms
FPS: 333, dt=3
Max FPS: 333
setVector ясное дело будет быстрее :) Вопрос не в том, как поднять FPS :) Мы так до С++ дойдем. Вопрос в том, что автор тестов не удосужился проверить свой код. А его в пример ставили другие люди и факапали Flash плеер )
Залил на другое — www.swfcabin.com/open/1378661623
Я там еще оказывается профакапил подкэшивать вектор в инициализации.
Руками переписывать на ас3 не стал, просто выбросил хэкс-код в ас3 и подправил косячки.
Вот исходник на ас3 — gist.github.com/ryzed/6487102
Вот на haxe — gist.github.com/ryzed/6487141
Да, должно быть быстрее.
Открыть не смог, чото геймтрах не эцсамое.
dt=0, значит меньше 1 мс.
Значит haxe победил!!11адынадынадын :)
Ничего не теряется в процессе intint->double->intint?
Я думал про такое, но нигде не пригодилось.
Вот 1200*800: gametrax.eu/game/7347692d94
Один хрен у меня нули показывает.
Новый ноут, затормозить трудно.
Она больше 60 показывать не умеет.
через setPixels или setVector, в текущем виде много времени съедается на вызов setPixel. Также использования алхимического доступа к памяти (domain memory API )может дать буст.
К примеру, строка вида x = 50 * 10 + i / f + 3*2 в as3 так и закомпилится. haxe же закомпилит сразу 500 + i / f + 6. Т.е. до выгрузки в swf вся математика, которая статическая — будет предварительно посчитана.
Ну и по инструкциям в ассемблере если смотреть — он льет более интересный код. На копейки быстрее. Я уже сформировал как ныть перед инжинерами, чтоб пересмотрели компилятор 1.0 у флеша, ведь 2.0 мало кто юзает.
Поправь еще раз название, правильно писать Haxe.
Всё! Победил я Haxe этот!
1) as3 + кунг-фу gametrax.eu/game/9461a62e7c
2) haxe gametrax.eu/game/071e94de01
Надеюсь ничего не напутал…
Из 63 fps на ас3 получили 77 простым телодвижением, как оказалось. Ну, не совсем простым. Но телодвижением :)
Короче, есть такой опкод add, который из стека вытягивает два значения и суммирует их. Но сначала типизирует. Так вот, в коде были строки pixel + colorModifier + r и прочие, которые складывались через add.
заменил add на add_i везде, где суммировались integer и это снесло мне шаблон.
плюс изменил немного инструкции по коду (влом уже проверять дало что-то или нет)…
Прошу глянуть 1 и 2 и отписаться fps и max fps
2. 38
564 @ 45
1. 576ms @ 42fps
2. 571ms @ 37fps
мне наиболее интересна сейчас система шаблонов в haxe. парсинг json файла можно проводить перед компиляцией, а не в рантайме, например.
очень большим для меня плюсом является система haxelib — есть реп с библиотеками, и их достаточно просто подключить и обновлять.
В разработке под флеш-онли платформу это не очень много особенностей.
С кроссплатформенностью всё равно достаточно много особенностей и приходится держать несколько веток проекта (или макросами #if #else #end пользоваться), но использоваться до 80% кода в одном проекте под разные платформы можно, но так со всеми кроссплатформенными либами, просо обычно это под капотом.
А если под яблодевайсы и андроиды писать, а не под флешплеер и андроиды (к примеру), то ещё проще все.
Вот в Unity3D есть возможность публиковать под xbox360 и ps3. Много людей ты знаешь, кто публикуются из Unity3D под эти платформы? В нашем сообществе еще никто вроде это не делал. Или просто не говорил.
Мне кажется надо целится на на платформы, а на качество игры. Когда игра сто процентов «пойдет» — тогда и решай, что с ней делать. Портировать самому или просто продать авторские права. И тогда её перепишут просто нативно, где ни один движок и рядом не станет.
Не, я не тру инди делаю и не как ryzed такие игры, а простенькую казуалку.
googledrive.com/host/0B-KnhhmWX_leZ0lZb2JmZ2ZuVlE/index.html
— это хакс?
Мой оптимизированный AS3 давал 120 ms.
Исходник в студию!:)
Haxe не сделал никакого чуда — он просто заменил некоторые вещи на более грамотные. Или просто «к месту» поставил те опкоды, которые нужны. А не поставаил те, которые подойдут. Но когда я во флеш уже в асме залепил небольшие корректировки — Haxе стал позади сразу же, т.к. у него все через статический класс отрабатывает. А он медленее, чем локальный класс вычисляется.
Что я хочу сказать. Несомненно флеш классный. Но если писать на хаксе — надо переучиваться. Не много, но надо. Он (как показал Ryzed) — выплюнул HTML5.
Ниже я писал, что html5 не запустился. Я ошибся. Запустился и только в safari. fps «так себе». Думаю если снять нагрузку в 2 раза — будет привлекательно исплючительно для топовых устройств. Они не увсех и еще не скоро будут у всех. А жить хочется сегодня, а не ждать завтра.
По-этому я не увидел ничего сверхестественного, что сделал хакс. Если иметь мозги, которых у меня нет, то можно написать небольшой микропатчер SWF файла и повесить его постобработкой и любая флешка станет шустрее работать. И менять среду разработки не придется.
Математические операции ускорял существенно. Правда я тестировал его давно, когда еще не было 11 плеера и ASC 2.0.
Но я сумел скрестить Flash + Haxe и получилось то, что в самой статье в Обновлении #2 лежит. Flash всё же уделал Haxe. Но мне правильно тут писали — много ли идиотов как я, кто будет этим заниматься?
Я понимаю, что если делать физические либы, то ручная подмена опкодов имеет смысл в любом случае. Но в случае с простым проектом — надо либо не иметь мозг и делать на чем удобнее (если не требуется супер оптимизация) либо писать патчер.
На счет «анала», кстати, я писал и не отказываюсь от своих слов. Там ненужные костяли в виде Flash.lib и Boot. У меня и без этого гемора всё хорошо на Flash работает. И быстрее.
Следует читать как
Надо же какой сюрприз.
samsung galaxy s3 — работает
iPhone 4S — работает
Это haxe, который в скомпилирован в js.
Потому и вынес отдельной веточкой.
640*480 и обработка в энтерфрейме.
googledrive.com/host/0B-KnhhmWX_leS1FrVWNyc3NHdXM/
Медленнее, чем флэш, но тут через setPixel() все делается.
1. 3636 @ 23
2. 562 @ 43
3. 554 @ 48
Ну и опять же методика измерения неправильная, на мой взгляд.
Если замерять числомолотилки, тогда надо нагружать по полной.
Можно добавить в runLoop() еще один внешний цикл, чтобы 10 раз по картинке пробегал.
И, разумеется, сравнивать человека с дизасмом в руках и тупой компилятор немного некорректно, я думаю :)
Я конечно очень удивился, почему haxe даже при кривом коде выплевывает более грамотный байткод. Но магию его разгадал. Компилятор хакса делали не индусы :D
Значение счетчика складывается в другую переменную, а потом счетчик инкрементируется.
Двойное присваивание.
Типа так:
курилкаAS3. Haxe тоже компилирует в «Флеш» (кроме еще нескольких платформ)forum.starling-framework.org/topic/as3-code-optimisation-learning-from-haxe
forum.starling-framework.org/topic/as3-code-optimisation-learning-from-haxe#post-43639
А вообще забавно, что эти блоги уже читают англоязычные програмеры.