
Быстрое удаление дисплейных объектов.
Собственно код:
Что в нем странного? (Слабонервным и непрограммистам просьба удалится на всякий случай).
Ну во-первых, то, что использование свойства numChildren (не поля, а свойства, которое дергается через метод, что затратнее, чем обращение к полю) не вносит существенных тормозов.
Раньше явываривал использовал такой код:
А теперь пользуюсь только Тайд! Но приведенный оптимальный вариант компактнее в записи и не требует дополнительных переменных.
Второе, это то, что removeChildAt(0) работает быстрее, чем удаление с конца списка или по произвольному индексу. Что говорит о том, что для дисплейных объектов используется скорее односвязный список с нехешированными индексами.
Тут надо заметить, что я не согласен с blooddy, у которого я почерпнул этот вариант кода, насчет криворукости программистов его создавших. Никаких общепринятых практик реализации дисплейных списков нет. Почему blooddy решил, что там не список, а массив и прочие придумки про удаленение с конца, никакого отношения к великим индусским гуру программирования не имеют. Как захотели так и сделали, главное оставив оптимальный вариант removeChildAt(0). Вот с конца было бы неоптимально удалять — надо было бы юзать или дополнительную переменную для индексации или делать действие над длинной removeChildAt(numChildren-1). Так что в этом случае все сделали хорошо и не с заходом сзади, как хотел blooddy (ну зачем же удалять с конца списка, если можно спереди?).
Поэтому я вознесу хвалу в этом посте великим гуру программирования, написавшим этот код. И знайте, о холиварщики и тролли мою объективность и стремление к познанию всепоглощающей Истины.
Любознательным хинт: если вдруг не знаете, то uint… Ой нет, это же хвалебный пост. Я напишу про него потом, хотя они и исправились. Ну если исправились, то напишу так: свободно используйте uint когда компилите под 10 плейер — все работает нормально. И вообще Адоб классные — флекс бесплатный, опенсорсный, глюки фиксят. Могут ведь, если захотят.
За окном играет музыка. Две школы недалеко. Сегодня выпускной. Дети будут веселиться. Пойду выпью чаю.
Чая я не выпил, но провел некоторые дополнительные исследования. Терпиливым хинт: Обращения к списку локальной переменной также чуть быстрее, чем занесение в переменную длинны списка.
Ну а еще я предоставляю исходник на чистом АС3, который я с недавнего времени очень полюбил в виду его бесплатности ну и немного из-за того, что компилит он быстрее чем из под ИДЕ:
while ( numChildren ) {removeChildAt(0);}
Что в нем странного? (Слабонервным и непрограммистам просьба удалится на всякий случай).
Ну во-первых, то, что использование свойства numChildren (не поля, а свойства, которое дергается через метод, что затратнее, чем обращение к полю) не вносит существенных тормозов.
Раньше я
i = numChildren; while (i--) removeChildAt(0);
Второе, это то, что removeChildAt(0) работает быстрее, чем удаление с конца списка или по произвольному индексу. Что говорит о том, что для дисплейных объектов используется скорее односвязный список с нехешированными индексами.
Тут надо заметить, что я не согласен с blooddy, у которого я почерпнул этот вариант кода, насчет криворукости программистов его создавших. Никаких общепринятых практик реализации дисплейных списков нет. Почему blooddy решил, что там не список, а массив и прочие придумки про удаленение с конца, никакого отношения к великим индусским гуру программирования не имеют. Как захотели так и сделали, главное оставив оптимальный вариант removeChildAt(0). Вот с конца было бы неоптимально удалять — надо было бы юзать или дополнительную переменную для индексации или делать действие над длинной removeChildAt(numChildren-1). Так что в этом случае все сделали хорошо и не с заходом сзади, как хотел blooddy (ну зачем же удалять с конца списка, если можно спереди?).
Поэтому я вознесу хвалу в этом посте великим гуру программирования, написавшим этот код. И знайте, о холиварщики и тролли мою объективность и стремление к познанию всепоглощающей Истины.
Любознательным хинт: если вдруг не знаете, то uint… Ой нет, это же хвалебный пост. Я напишу про него потом, хотя они и исправились. Ну если исправились, то напишу так: свободно используйте uint когда компилите под 10 плейер — все работает нормально. И вообще Адоб классные — флекс бесплатный, опенсорсный, глюки фиксят. Могут ведь, если захотят.
За окном играет музыка. Две школы недалеко. Сегодня выпускной. Дети будут веселиться. Пойду выпью чаю.
Чая я не выпил, но провел некоторые дополнительные исследования. Терпиливым хинт: Обращения к списку локальной переменной также чуть быстрее, чем занесение в переменную длинны списка.
while (spr.numChildren) { spr.removeChildAt(0);}
— чуть быстрее чемi = spr.numChildren; while (i--) { spr.removeChildAt(0);}
Ну а еще я предоставляю исходник на чистом АС3, который я с недавнего времени очень полюбил в виду его бесплатности ну и немного из-за того, что компилит он быстрее чем из под ИДЕ:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.getTimer;
/**
* @author Puzzlesea
*/
public class Main extends Sprite {
protected const ITERATIONS:int = 3000;
// 1234567890
protected var out:String = "";
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var i:int;
var time:uint;
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
for ( i = 0; i < ITERATIONS; i++) removeChildAt(0);
log("Test "+ ITERATIONS +" times removeChildAt(0) [for i++]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
for ( i = ITERATIONS; i > 0; i--) removeChildAt(0);
log("Test " + ITERATIONS +" times removeChildAt(0) [for i--]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
for ( i = ITERATIONS; i > 0;) removeChildAt(--i);
log("Test " + ITERATIONS +" times removeChildAt(i) [for removeChildAt(--i)]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
i = numChildren;
while (i--) removeChildAt(0);
log("Test " + ITERATIONS +" times removeChildAt(0) [while i--]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
i = numChildren;
while (--i) removeChildAt(0);
log("Test " + ITERATIONS +" times removeChildAt(0) [while --i]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
var mi:int = numChildren;
i = 0;
while (i < mi) { removeChildAt(0); i++;}
log("Test " + ITERATIONS +" times removeChildAt(0) [while i++]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
mi= numChildren;
i = 0;
while (i++ < mi) { removeChildAt(0);}
log("Test " + ITERATIONS +" times removeChildAt(0) [while i++]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) addChild(new Sprite());
time = getTimer();
while (numChildren) {removeChildAt(0);}
log("Test " + ITERATIONS +" times removeChildAt(0) [while numChildren]" + (getTimer() - time));
log("---------------------------------------");
var spr:Sprite = new Sprite;
for ( i = 0; i < ITERATIONS; i++) spr.addChild(new Sprite());
time = getTimer();
while (spr.numChildren) { spr.removeChildAt(0);}
log("Test " + ITERATIONS +" times spr.removeChildAt(0) [while spr.numChildren]" + (getTimer() - time));
for ( i = 0; i < ITERATIONS; i++) spr.addChild(new Sprite());
time = getTimer();
i = spr.numChildren;
while (i--) { spr.removeChildAt(0);}
log("Test " + ITERATIONS +" times spr.removeChildAt(0) [while i--]" + (getTimer() - time));
//print results
print_log();
}
protected function log(str:String=""):void { out += str + "\n"; }
protected function print_log(ax:Number=0, ay:Number=0):void {
var fld:TextField = new TextField;
fld.defaultTextFormat = new TextFormat("Tahoma,Verdana", 11);
fld.autoSize = "left"; //TextFieldAutoSize.LEFT;
fld.x = ax;
fld.y = ay;
fld.text = out;
addChild(fld);
}
}
}
Неплохой такой темплейтик для разных тестов. Гикам оптимизации рекомендую! Сам готовил :)
- +5
- puzzlesea
Комментарии (9)
Правда я, в любом случае, чистыми спрайтами не пользуюсь и сохраняю ссылки на всех детей самостоятельно.
Обычно такая цепочка вложенности: stage > Game > Screen > тут уже всякое.
чистыми спрайтами не пользуюсь и сохраняю ссылки на всех детей
О а как это? Ручками рендер в битмапу? Или ты имеешь в виду, что в переменные все дисплейные объекты заносишь?
И ссылки все храню в списках/массивах.
Удобно пробегать по всем объектам и память не течет.
Рендер как получится. Можно в битмапу, можно просто добавлять в контейнер.
По ситуации.
«The getChildAt() method is faster than the getChildByName() method. The getChildAt() method accesses a child from a cached array, whereas the getChildByName() method has to traverse a linked list to access a child.»
puzzlesea, малодца!