четверг, марта 20, 2008

Повышение производительности AS3 приложений

Здесь представлены некоторые приемы, которые помогут повысить производительность наших приложений:

1) Создавайте константы для часто используемых объектов типа new Point(0,0) или new Rectangle(0,0,320,240):

//вызов 100000 раз: 75мс
new Point(0,0);
//или
private static const POINT:Point = new Point(0,0);
//8мс
POINT;


Быстрее на 838%

2) Сократите указания на статические члены классов. Вместо этого старайтесь использовать переменные пакета:
//15мс
SomeClass.somevar;
package somepackage{
public const somevar:int;
}
//8мс
somevar;

на 66% быстрее

3) Сохраняйте getter свойства в локальных переменных при их использовании более одного раза.

somesprite.graphics.clear();
somesprite.graphics.beginFill(0x000000);
somesprite.graphics.drawRect(0,0,10,10);
somesprite.graphics.endFill();

// лучше заменить на

var n:Graphics = somesprite.graphics;
n.clear();
n.beginFill(0x000000);
n.drawRect(0,0,10,10);
n.endFill();


4) Создавайте собственные reflection-методы вместо использования getDefinitionByName(getQualifiedClassName(object))
utils reflection
// 503мс
var someclass:Class = getDefinitionByName(getQualifiedClassName(someObject));
// getter reflection
public class SomeClass {
public function get reflect():Class {
return SomeClass;
}
}
// 9мс
var someclass:Class = object.reflect();

быстрее на 5489%

5) Страрайтесь использовать строгое типизирование

6) Приводите к нужным типам, например, при чтении из массива.
Быстрее будет обращаться к image

var image: BitmapData = images[index];
image.getPixel(x,y)
//чем к
images[index].getPixel(x,y);


7) Где возможно, используйте int вместо Number

8) Операторы побитового сдвига работают быстрее:

Побитовый сдвиг влево быстрее на 300% при умножении на любую степень двойки:

x = x * 2;
x = x * 64;
//равно:
x = x << 1;
x = x << 6;


Побитовый сдвиг вправо быстрее на 350% при делении на любую степень двойки:

x = x / 2;
x = x / 64;
//равно:
x = x >> 1;
x = x >> 6;


Извлечение компонентов цвета:

//24bit
var color:uint = 0x336699;
var r:uint = color >> 16;
var g:uint = color >> 8 & 0xFF;
var b:uint = color & 0xFF;
//32bit
var color:uint = 0xff336699;
var a:uint = color >>> 24;
var r:uint = color >>> 16 & 0xFF;
var g:uint = color >>> 8 & 0xFF;
var b:uint = color & 0xFF;


Объединение компонентов цвета:

//24bit
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = r << 16 | g << 8 | b;

//32bit
var a:uint = 0xff;
var r:uint = 0x33;
var g:uint = 0x66;
var b:uint = 0x99;
var color:uint = a << 24 | r << 16 | g << 8 | b;


9) Обмен значениями численных переменных без использования временной переменной:

var t:int = a;
a = b;
b = t;
//равно:
a ^= b;
b ^= a;
a ^= b;


Быстрее на 20%.

10) Инкремент/декремент.
Внимание: это пример понижения производительности, но зато есть возможность понизить читабельность кода для врагов:)

i = -~i; // i++
i = ~-i; // i--


11) Смена знака с помощью NOT или XOR (говорят на 300% быстрее):

i = -i;
//равно:
i = ~i + 1;
//или
i = (i ^ -1) + 1;


12) Подсчет остатка

Если делитель является степенью двух, то остаток можно подсчитать быстрее на 600% следующим образом:
остаток = делимое & (делитель - 1);

x = 131 % 4;
//равно:
x = 131 & (4 - 1);


13) Проверка на четность/нечетность:

isEven = (i % 2) == 0;
//равно:
isEven = (i & 1) == 0;


Быстрее на 600%.

14) Абсолютное значение. Версия 1 быстрее на 250%, чем Math.abs(), а версия 2 быстрее на 20%, чем версия 1.

//версия 1
i = x < 0 ? -x : x;
//версия 2
i = (x ^ (x >> 31)) - (x >> 31);


15) Сравнение двух числе на равенство знаков

eqSign = a * b > 0;
//равно:
eqSign = a ^ b >= 0;


На 35% быстрее.

16) Быстрое конвертирование цвета из R5G5B5 в R8G8B8

R8 = (R5 << 3) | (R5 >> 2)
G8 = (R5 << 3) | (R5 >> 2)
B8 = (R5 << 3) | (R5 >> 2)

17) a++ быстрее, чем a = a + 1 и т.п.

18) Умножение быстрее деления.

Лучше использовать a = b*.5 вместо a = b / 2

19) int(1.5) быстрее, чем Math.floor(1.5)
Аналогично int(1.5) + 1 быстрее, чем Math.ceil(1.5)

35 комментариев:

Анонимный комментирует...

Очень хорошая подборка. Спасибо

Анонимный комментирует...

Отлично )

Анонимный комментирует...

а можно про 14 вариант по подробнее ?

Andrey Gorbatov комментирует...

блоггер накосячил со знаками больше/меньше, наставил каких-то кавычек и съел некоторые примеры. вроде все исправил)

Анонимный комментирует...

о! другое дело :) а то я думал что пора уже в отпуск :)

Unknown комментирует...

Отличные примерчики... буду рекомендовать всем к прочтению.

Анонимный комментирует...

а что быстрее
a = b * 0.5;
или
a = b >> 1;

Анонимный комментирует...

Use int for counters and array lookups (AS3 only)

Use Number for math operations. There are cases where int is faster but it is generally best to stick with Number (AS3 only)

http://thinkswedish.com/#ContentHolder:feed=blog&Entries:0=entry+1=877

Andrey Gorbatov комментирует...

по поводу:

а что быстрее
a = b * 0.5; //1564
или
a = b >> 1; //1548

у меня вышло вот так.

Andrey Gorbatov комментирует...

насчет 2500% в получении модуля скорее всего опечатка. у меня вышло порядка 250.

k0zer комментирует...

>> Аналогично int(1.5) + 1 быстрее, чем Math.ceil(1.5)

Довольно часто вижу этот рецепт по оптимизации, но почему-то нигде не пишется, что он не всегда адекватный.
int(2) + 1 == 3
Math.ceil(2) == 2

Хотя для рандома, который 0 <= random() < 1, не критично Math.ceil() заменить:
например
1 <=(int(10 * Math.random()) + 1) <= 10

Анонимный комментирует...

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

Дмитрий Алексеевич комментирует...

Joa Ebert собирает вики по оптимизации - http://je2050.de/files/misc/as3opt.pdf

Александр комментирует...

Спасибо за полезную информацию

Mikhail комментирует...

Вверх округлять лучше как:
int(x + 0.9999).

FOr3st комментирует...

Очень круто, спасибо огромное! =)

Jekyll комментирует...

ух ты)
Спасибо!

zimer комментирует...

константу на объект класса Point создавать нельзя, т.к. Point может изменяться (не immutable)

Анонимный комментирует...

Почему на блоге так мало тем про кризис, Вас этот вопрос не волнует?

Анонимный комментирует...

Автор, а Вы в каком городе живете если не секрет?

Анонимный комментирует...

Заметил такую тенденцию, что в блогах появилось много не адекватных комментариев, не могу понять, это что кто то спамит так? А зачем, чтоб падлу комуто сделать))) Имхо глупо…

Анонимный комментирует...

Суперский пост! Блог уже в ридере )

Анонимный комментирует...

A chto dlya vas vash blog? Vi proffesional’niy blogger ili eto prosto dlya dushi?

Анонимный комментирует...

Зачетный пост, спасибо!

Анонимный комментирует...

Даже и не придирешься!

Анонимный комментирует...

Автор, а Вы в каком городе живете если не секрет?

Анонимный комментирует...

Супер статья! Подписался на RSS, буду следить =)

Анонимный комментирует...

Вам будет интересно - курс английского языка
piercing
buy cheap regrowth

Анонимный комментирует...

Интересно написано....но многое остается непонятнымb

Анонимный комментирует...

всех с празников

Анонимный комментирует...

Очень интересная статья вышла! Респект автору! :)

Анонимный комментирует...

Прикольные слова

Анонимный комментирует...

Я могу проконсультировать Вас по этому вопросу и специально зарегистрировался, чтобы поучаствовать в обсуждении.

Анонимный комментирует...

Хоть убей, не знаю.

Анонимный комментирует...

Бесподобное сообщение, мне очень нравится :)