Как ускорить циклы в ActionScript? - PullRequest
0 голосов
/ 08 марта 2011

Эй, ребята,
Я писал движок для радиопередачи в ActionScript 3 и получал ужасную производительность.
Сначала я подумал, что это очевидно: радиопередача требует интенсивной математики, и я должен получать низкую частоту кадров из-за сложной математики, однако, к моему удивлению, это оказалось не так; кажется, что причиной является петля for, которая рисует стены.

Я попытался поэкспериментировать с моим кодом и обнаружил, что когда я закомментировал цикл for, FPS более чем удвоился, но когда я раскомментировал цикл for, но оставив код рисования, прокомментировал FPS наполовину. Действительно ли ActionScript настолько медленный, что сам по себе простой цикл должен израсходовать столько процессорного времени?

Спасибо за любой вклад!

Вот код, о котором идет речь (примечание Quck: COLUMN_SIZE - это просто константа, определенная как 1):

var y:int = 0;
var x:int = 0;
var rx:int = 0;

for( x = 0; x < COLUMN_SIZE; x++ ) {

    yt = ys;
    rx = x + sx;
    for( y = yTop; y < yBot; y++ ) {

        var idx:int = int((stage.stageWidth*y)+rx);

        pBuffer[idx] = getTexturePixel(ray.tile-1, ray.texel, int(yt), ray.horz);
        yt += yi;

    }
}

Ответы [ 5 ]

3 голосов
/ 08 марта 2011

уменьшается, пока говорят, что петли быстрее.

изменяется в зависимости от версии проигрывателя, версии браузера, типов ОС и различных параметров (тип увеличенного объекта, условия прерывания ....).

самый быстрый способ обработки списков объектов - это использование связанных списков. Я не знаю, если (и как) это применимо здесь.

как долго этот цикл y = yTop -> yBot?

нет причин, по которым он так сильно отстает, и в любом случае хорошая новость заключается в том, что ваш метод getTexturePixel () работает быстро

в противном случае доступ к значениям внутри объекта всегда медленнее, чем их локальное хранение

stage.stageWidth//won't change during the loops :)

//and maybe also
ray.tile-1, ray.texel, int(yt), ray.horz

если эти значения не обновляются во время цикла Y, то может быть полезно сохранить их до цикла Y.

1 голос
/ 09 марта 2011

Мой единственный конкретный совет - удостовериться, что вы не смешиваете числа и числа в сравнении и в математике, убедитесь, что вы используете как можно больше локальных объектов, и старайтесь избегать погони за свойствами объекта во внутренних циклах.

Эти два документа предоставят небольшое руководство по дополнительным вещам, которые вы можете попробовать:

http://onflex.org/ACDS/AS3TuningInsideAVM2JIT.pdf

http://help.adobe.com/en_US/as3/mobile/flashplatform_optimizing_content.pdf

1 голос
/ 08 марта 2011

У меня есть три вещи, которые могут вам немного помочь var x и y не нужно объявлять наверху, не знаю, получите ли вы повышение производительности за то, что не ссылаетесь на существующую часть памяти, поэтому сделайте ваши циклы for for(var x:int = 0; x < COLUMN_SIZE; x++ ) { && for(var y:int = yTop; y< yBot; y++){, а также вы вводите типы почему-то от целых до целых чисел var idx:int = (stage.stageWidth*y)+rx; надеюсь, что эти идеи вам вообще помогут. о, и ссылка, которая может вам помочь. http://www.experts -exchange.com / Программное обеспечение / Photos_Graphics / Web_Graphics / Macromedia_Flash / ActionScript / A_2107-20-советы к Оптимизировать-ваш-ActionScript.html

0 голосов
/ 09 марта 2011

Трудно сказать, основываясь исключительно на приведенном коде, но похоже, что у вас, возможно, там работает алгоритм On ^ 2, когда он вам не нужен. Возможно ли, что вы тестируете в 2 раза больше, чем нужно? Позвольте мне продемонстрировать, что я имею в виду ...

for(var i:int = 0 ; i < 1000 ; i++){
    for(var j:int = 0 ; j < 1000 ; j++){
        // This can be pretty wasteful in certain situations...
        // for example, if you're collision detecting between
        // all objects on a field, you are performing twice the
        // comparisons you need to when you start j over at 0
        // every time.
    }
}

Возможно ли, что вместо этого вы можете сделать что-то подобное?

for(var i:int = 0 ; i < 1000 ; i++){
     for(var j:int = i + 1 ; j < 1000 ; j++){
         // Now you won't compare the same two values more than once...
     }
}

Это дает вам On ^ 1/2 вместо On ^ 2, что не удивительно, но будет в 2 раза быстрее. Я не знаю, применим ли этот совет вообще к вашему радиовещанию (возможно, вам действительно нужно начинать все заново с одного и того же места во внутреннем цикле!), Но это тот, который помог мне в прошлом при столкновениях. 1007 *

0 голосов
/ 08 марта 2011

Почему линия getTexturePixel(...) находится даже внутри внутреннего цикла?

Если эти значения не изменены, его следует вызывать вне цикла, сохранять в кэше, а затем кэшированное значение следует сохранять в позиции массива.

    cachedPixel = getTexturePixel(ray.tile-1, ray.texel, int(yt), ray.horz);

    for( y = yTop; y < yBot; y++ )
    {
        var idx:int = int((stage.stageWidth*y)+rx);

        pBuffer[idx] = cachedPixel;
        yt += yi;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...