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 файлик и смотрим код проекта (он зачем-то в кадре):


Первым непониманием стала конструкция:
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

Комментарии (92)

+3
Ну, кстати, да — часто тесты производительности делаются людьми, хорошо разбирающимися в одной технологии и более-менее — в другой, для того, чтобы в очередной раз доказать, что «их» технология — лучше. Потому нет повода верить в то, что оба примера будут хорошо оптимизированы.
  • SeeD
  • SeeD
+1
740 100
120 200
269 200
i7-3630QM

Тогда тесты должны делать 2 человека, в формате соревнования, где цель сделать программу быстрее чем у оппонента, конечно с условиям приблизительно равных сил))
0
1. 1439ms @ 63fps
2. 233ms @ 145fps
3. 675ms @ 200fps

Проц: Core i3 CPU 550 @ 3200GHz
0
Вот результаты на AMD C-50 1Ghz + debug player :)

1) 12,416 ms @ 8 fps
2) 1,049 ms @ 22 fps
3) 4,320 ms @ 21 fps
0
1) 3557 @ 31
2) 265 @ 71
3) 1209 @ 71
+1
Да что тут думать… Галимый тест был у первоначального автора:) Только стоит предположить, что версию на HaXe он тоже не сильно оптимизировал:)
0
В том и дело, что везде по нету публикую бенчмарки того или иного рода. Когда делаешь проверку сам — все становится на места.
Я отдельно для себя делал версию 1920х1080 — флеш на 1 fps выдавал в итоге больше. При том, что я всунул кеширование в хаксовский пример (тоже отдельно). Не поленился старый ноут включил — что хакс версия, что флеш — выдают одинаковые fps. Правда флеш еще в 2.5 раза быстрее рисует фрактал изначально. Хочу, чтоб этот пример опытный хаксер оптимизировал :) Хочу другой тест.
0
Core i5 2.8 GHz

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
0
… если провести дальнейшую типизацию переменных, ты не со всеми это успел:)
0
Я очень давно заметил, что неправильная типизация или её отсутствие убивает всю скорость. Поэтому приличные IDE для кодинга помогают избежать такого, постоянно выдавая ошибки и варнинги.
0
Ты хакс оптимизировал? Скинь плиз файлик
0
Нет, это оптимизированный AS3.
0
Клево :) Что-то пропустил я. Видишь — все равно можно больше выжать. Где что заменил ты?
+1
beforeTime типизировал, вместо afterTime влепил getTimer() прямо в формулу. Некоторые типы поменял с int на uint. Некоторые поля класса переделал в локальные переменные…
0
Код на HaXe глянул, его точно такими же методами можно оптимизировать. Только вот я не умею компилить на HaXe, и разбираться в нём западло:)
0
Я уже разобрался с Хаксом. Компилить его относительно просто. Но лучше я дождусь человека, чтоб потом небыло предьяв типа я черепаху сравниваю с самолетом :) Тем более статья для того, чтоб люди в очередной раз перестали тупо верить во все написанное, а проверяли сами :)
0
Ну там, на деле, не так много оптимизировать. В обоих тестах можно убрать нафик setInterval, и сделать обычный enterFrame. При этом просто считать время тем же getTimer(). Один простой цикл как-то супер-интересно оптимизировать врядли получится. Если только нет где-то в компиляторе какой-нить модной галочки, которая ускоряет всё в два раза (как у меня с AIR под iOS вышло:)).
0
У меня на флэштестах FPS = infinity, а на haxe = 0 :)
Но немного оптимизировать можно, я думаю, в обоих вариантах.
  • ryzed
  • ryzed
0
Да вот на старом ноуте тоже заметил прикол такой :) Хз что это такое
0
Предлагаю увеличить размер в два раза или побольше, иначе апдейт текстфилда с фпс будет жрать больше, чем сам фрактал.
0
Сейчас залью интересный апдейт
0
Где?!
0
Ну так я другое заливал:

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 меряю
0
Мои не смотрел?
Сколько показывает? Мерялка одинаковая.
0
Раз в 15 быстрее.
0
640*480

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 плеер )
0
Если не трудно — запили плиз чистый флеш вариант 1200*800 с set/get векторами
+1
Как Ромикс и писал, геймтрах переезжает на новый сервер и поэтому временно не работает.
Залил на другое — www.swfcabin.com/open/1378661623

Я там еще оказывается профакапил подкэшивать вектор в инициализации.
Руками переписывать на ас3 не стал, просто выбросил хэкс-код в ас3 и подправил косячки.
Вот исходник на ас3 — gist.github.com/ryzed/6487102
Вот на haxe — gist.github.com/ryzed/6487141
+1
Добавлю свои 5 копеек. Мой вариант на haxe 1200x800 плюс немного алхимии. Генерацию ускорить не удалось, а фпс на моем компе немного выше ryzed варианта в одинаковых условиях: gametrax.eu/game/55795d13a2
0
Через flash.Memory?
Да, должно быть быстрее.
Открыть не смог, чото геймтрах не эцсамое.
+1
Продублировал dl.dropboxusercontent.com/u/1036911/HXJointForces/TestMandel.swf
0
Нули показывает, как и в моем варианте.
dt=0, значит меньше 1 мс.
Значит haxe победил!!11адынадынадын :)
0
Еще приятный бонус алхимической памяти в такого рода задачах — с цветовыми компонентами можно работать напрямую побайтно, отпадает необходимость постоянно сплитить/склеивать цвета. И еще можно копировать по два пикселя за раз, как Double.
0
С даблом работает нормально?
Ничего не теряется в процессе intint->double->intint?
Я думал про такое, но нигде не пригодилось.
0
Нормально, не теряется.
0
Вот 640*480: gametrax.eu/game/489b257a8a
Вот 1200*800: gametrax.eu/game/7347692d94

Один хрен у меня нули показывает.
Новый ноут, затормозить трудно.
0
Думаю надо измерять несколько кадров, например каждые 100 кадров замерять время.
0
Вот еще на 1200 со стандартной мерялкой: gametrax.eu/game/fd0d3644e1
Она больше 60 показывать не умеет.
0
В обоих вариантах нужно использовать одномерный массив и заливку делать
через setPixels или setVector, в текущем виде много времени съедается на вызов setPixel. Также использования алхимического доступа к памяти (domain memory API )может дать буст.
0
Спасибо, капитан :)
0
You're welcome!
0
Из всей этой болтовни я так и не понял, кому и нах нужен HaXe? Быстрее ли он? В чём он быстрее?
0
Хакс быстрее за счет более грамотной компиляции. На много? Не совсем и не всегда. Но я могу ошибаться, т.к. у меня нет реального небольшого приложения, где была бы разница в 20fps, чтоб можно было о чем-то говорить. А в кривых исходниках автора разница большая была. А потом она практически исчезла. Хаксу надо отдать должное — он малость думает за разработчика.

К примеру, строка вида x = 50 * 10 + i / f + 3*2 в as3 так и закомпилится. haxe же закомпилит сразу 500 + i / f + 6. Т.е. до выгрузки в swf вся математика, которая статическая — будет предварительно посчитана.

Ну и по инструкциям в ассемблере если смотреть — он льет более интересный код. На копейки быстрее. Я уже сформировал как ныть перед инжинерами, чтоб пересмотрели компилятор 1.0 у флеша, ведь 2.0 мало кто юзает.
0
Да и компилятор у него, был по-крайней мере, быстрее. Непонятно почему адоб со своими ресурсами не могли довести до ума свой.

Поправь еще раз название, правильно писать Haxe.
0
ЗЫ Ну а кривых бенчмарков и на флеш вс флеш хватает, так что на этой основе тоже делать какие-то выводы не стоит.
0
Я вот юзаю компилятор 2.0, но не в курсе, чем он круче:)
+1
А ты юзаешь из него методы 2.0? если нет, то он до фени. У меня тут прорыв ппц! Надо полтарушку достать…

Всё! Победил я 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
0
1. 42
2. 38
0
Зачет! Спасибо :)
0
Заменять add на add_i — это конечно круто, но не каждый же полезет в низкоуровневые инструкции:) Можно ли это сделать просто в коде (AS)?
0
Одинаково, по 67.
0
545 @ 50
564 @ 45
0
Проц: i7 920
1. 576ms @ 42fps
2. 571ms @ 37fps
0
там достаточно много своих плюшек сейчас (в третьей версии).
мне наиболее интересна сейчас система шаблонов в haxe. парсинг json файла можно проводить перед компиляцией, а не в рантайме, например.
очень большим для меня плюсом является система haxelib — есть реп с библиотеками, и их достаточно просто подключить и обновлять.
В разработке под флеш-онли платформу это не очень много особенностей.
С кроссплатформенностью всё равно достаточно много особенностей и приходится держать несколько веток проекта (или макросами #if #else #end пользоваться), но использоваться до 80% кода в одном проекте под разные платформы можно, но так со всеми кроссплатформенными либами, просо обычно это под капотом.
А если под яблодевайсы и андроиды писать, а не под флешплеер и андроиды (к примеру), то ещё проще все.
0
Так это, если простенькую игру писать можно на чем угодно, то лучше хекс ибо там мультиплатформа, так же?
0
На этот счет я ничего не скажу, т.к. мультиплатформа слишком громко звучит, а haxe мой опыт примерно 1 из 10.
Вот в Unity3D есть возможность публиковать под xbox360 и ps3. Много людей ты знаешь, кто публикуются из Unity3D под эти платформы? В нашем сообществе еще никто вроде это не делал. Или просто не говорил.

Мне кажется надо целится на на платформы, а на качество игры. Когда игра сто процентов «пойдет» — тогда и решай, что с ней делать. Портировать самому или просто продать авторские права. И тогда её перепишут просто нативно, где ни один движок и рядом не станет.
0
Вот в Unity3D есть возможность публиковать под xbox360 и ps3. Много людей ты знаешь, кто публикуются из Unity3D под эти платформы? В нашем сообществе еще никто вроде это не делал. Или просто не говорил.
четверых.
Мне кажется надо целится на на платформы, а на качество игры. Когда игра сто процентов «пойдет» — тогда и решай, что с ней делать. Портировать самому или просто продать авторские права. И тогда её перепишут просто нативно, где ни один движок и рядом не станет.
Не, я не тру инди делаю и не как ryzed такие игры, а простенькую казуалку.
0
хз :D пили html5. работать будет везде. Но плохо. Но везде!
+1
Кстати проблема не в юнити, а с самими корпорациями. Нужно много денег + знать нужных людей, в русских реалиях это тяжело как минимум из-за второго пункта. На кежуал коннекте типы говорили " ну да, я созвонился с гейм директором из сони, мы поели пиццку, пошли в студию, где снимали Гарри Поттера и там бла бла бла..." Тут можно только сказать «ну да, я с ним по скайпу поговорил и чтобы убедить его, что я не фейк мне пришлось сфоткаться с банкой огурцов на голове.» В принципе классические платформеры заточить под джойтик не особо сложно.
0
В принципе классические платформеры заточить под джойтик не особо сложно.
Погуглил одну из немногих доставляющих игр на юнити, которую прошел. Да, она есть на пс3
+7
Просто оставлю это тут :)
googledrive.com/host/0B-KnhhmWX_leZ0lZb2JmZ2ZuVlE/index.html
  • ryzed
  • ryzed
+3
0
googledrive.com/host/0B-KnhhmWX_leZ0lZb2JmZ2ZuVlE/index.html
— это хакс?
0
Вот этот твой вариант у меня даёт 38 ms.
Мой оптимизированный AS3 давал 120 ms.
Исходник в студию!:)
0
Этож html5 от haxe:)
0
О как… А это даже и не флеш…
0
В смысле это haxe через html5? Да ну вас всех… Обсуждали, по-моему, производительность в пределах флеш-плеера:) Давайте ещё на С++ напишем версию.
0
Ну TheRabbit итак полез опкоды менять )
0
Не, я уже сказал (или думал, что сказал) выше. Если брать чистый и качественный as3 и haxe — то haxe генерит более грамотный код, дико оптимизированный под виртуальную машину. Flash CC на удивление сделал бинарник лучше, чем Flash Builder 4.7. Но на производительность это не повлияло. Оба затупили.

Haxe не сделал никакого чуда — он просто заменил некоторые вещи на более грамотные. Или просто «к месту» поставил те опкоды, которые нужны. А не поставаил те, которые подойдут. Но когда я во флеш уже в асме залепил небольшие корректировки — Haxе стал позади сразу же, т.к. у него все через статический класс отрабатывает. А он медленее, чем локальный класс вычисляется.

Что я хочу сказать. Несомненно флеш классный. Но если писать на хаксе — надо переучиваться. Не много, но надо. Он (как показал Ryzed) — выплюнул HTML5.

Ниже я писал, что html5 не запустился. Я ошибся. Запустился и только в safari. fps «так себе». Думаю если снять нагрузку в 2 раза — будет привлекательно исплючительно для топовых устройств. Они не увсех и еще не скоро будут у всех. А жить хочется сегодня, а не ждать завтра.

По-этому я не увидел ничего сверхестественного, что сделал хакс. Если иметь мозги, которых у меня нет, то можно написать небольшой микропатчер SWF файла и повесить его постобработкой и любая флешка станет шустрее работать. И менять среду разработки не придется.
0
Есть такой «патчер» — code.google.com/p/apparat/
Математические операции ускорял существенно. Правда я тестировал его давно, когда еще не было 11 плеера и ASC 2.0.
+1
Кролик, ты бы определился уже :D

Haxe ну прям анал генерирует. Я не понимаю как оно вообще работает

Haxe генерит более грамотный код, дико оптимизированный под виртуальную машину.
0
В том и дело, что анальные инструкции Haxe работают каким-то боком быстрее и идут в разрез моей логики. Но на то она и моя, что у более умных людей все более «понятно» что-ли будет :)

Но я сумел скрестить Flash + Haxe и получилось то, что в самой статье в Обновлении #2 лежит. Flash всё же уделал Haxe. Но мне правильно тут писали — много ли идиотов как я, кто будет этим заниматься?

Я понимаю, что если делать физические либы, то ручная подмена опкодов имеет смысл в любом случае. Но в случае с простым проектом — надо либо не иметь мозг и делать на чем удобнее (если не требуется супер оптимизация) либо писать патчер.

На счет «анала», кстати, я писал и не отказываюсь от своих слов. Там ненужные костяли в виде Flash.lib и Boot. У меня и без этого гемора всё хорошо на Flash работает. И быстрее.
+3
Добавлю для бугурта.

Flash всё же уделал Haxe.
Следует читать как
flash + человек с дизасмом + время + синтетический тест + кривая мерялка смогли выиграть 15% процентов производительности у тупого компилятора haxe в штатной поставке.
Надо же какой сюрприз.
Комментарий был удален
+2
ненужные костяли в виде Flash.lib и Boot
Не знаю было ли это вызвано именно этим, но некоторое время назад, флешдекомпилеры тупо не видели код Хэкса, который был запрятан в Boot. Потом научились. Так что раньше это имело еще смысл и в качестве защиты кода. А поскольку Николя на индуса не похож, то полагаю, что был именно этот или другой замысел, а не быдлокодинг ниразу. Если этот — то устарел уже, но работать не мешает.
0
говноhtml5. На iPad4 не работает
0
twitter.com/ryzzed/status/376826704552919040
samsung galaxy s3 — работает
iPhone 4S — работает
0
Да, выше я отписался. Работает, но еле еле. И быстрее никогда не будет.
0
Я там в комментах исходник постил же, тут правда переделанный обратно на setPixel()
Это haxe, который в скомпилирован в js.
Потому и вынес отдельной веточкой.
0
Вот тут немного побольше.
640*480 и обработка в энтерфрейме.
googledrive.com/host/0B-KnhhmWX_leS1FrVWNyc3NHdXM/
Медленнее, чем флэш, но тут через setPixel() все делается.
0
Проц: i5 2450M
1. 3636 @ 23
2. 562 @ 43
3. 554 @ 48
+3
А почему у тебя в ас3 используется вайл, а в haxe фор?

Ну и опять же методика измерения неправильная, на мой взгляд.
Если замерять числомолотилки, тогда надо нагружать по полной.
Можно добавить в runLoop() еще один внешний цикл, чтобы 10 раз по картинке пробегал.

И, разумеется, сравнивать человека с дизасмом в руках и тупой компилятор немного некорректно, я думаю :)
  • ryzed
  • ryzed
0
Потому, что while из ас3 компилируется так же как и for из haxe, сравнивания бинарный код.

Я конечно очень удивился, почему haxe даже при кривом коде выплевывает более грамотный байткод. Но магию его разгадал. Компилятор хакса делали не индусы :D
0
В фор на haxe есть лишний оверхед из-за концепции итераторов.
Значение счетчика складывается в другую переменную, а потом счетчик инкрементируется.
Двойное присваивание.

Типа так:
var _g11 : int = 0;
                                var _g2 : int = vars.length();
                                while(_g11 < _g2) {
                                        var i1 : int = _g11++;
                                }
+1
я вообще не понимаю, что тут происходит.
+1
если в кратце: Флеш жив! :)
0
речь скорее про попытку доказать что жив курилка AS3. Haxe тоже компилирует в «Флеш» (кроме еще нескольких платформ)
0
тсс это я знаю. дай порадовать человека :D
+1
Кролик демонстрирует искусство кунгфу
0
Даниэль (Старлинг) офигевает от ваших тестов:)
forum.starling-framework.org/topic/as3-code-optimisation-learning-from-haxe
+1
Лол: там предлагают индусский код называть адобовским кодом, чтоб не быть расистом (*катаюсь*)
forum.starling-framework.org/topic/as3-code-optimisation-learning-from-haxe#post-43639

А вообще забавно, что эти блоги уже читают англоязычные програмеры.
0
А вообще забавно, что эти блоги уже читают англоязычные програмеры.
Да этот Scol или наш или плотно работает с нашими.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.