Быстрое удаление дисплейных объектов.

Собственно код:
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);
                }
        }
        
}
Неплохой такой темплейтик для разных тестов. Гикам оптимизации рекомендую! Сам готовил :)

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

0
Спасибо за инфу, интересно.
Правда я, в любом случае, чистыми спрайтами не пользуюсь и сохраняю ссылки на всех детей самостоятельно.
0
И всё на стейдж кладешь?
0
Не обязательно.
Обычно такая цепочка вложенности: stage > Game > Screen > тут уже всякое.
0
Пожалуйста :)
чистыми спрайтами не пользуюсь и сохраняю ссылки на всех детей
О а как это? Ручками рендер в битмапу? Или ты имеешь в виду, что в переменные все дисплейные объекты заносишь?
0
Практически для всего делаю наследников от базовых объектов.
И ссылки все храню в списках/массивах.
Удобно пробегать по всем объектам и память не течет.

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

«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.»
0
О спасибо, значит хеш по индексам есть. Тогда очень странно, что индексный доступ работает медленно. Получается, что скорость должна быть равномерная, если только они не зачудили с самим хешем индексов.
0
Давно юзаю такой вариант удаления объектов, не помню уже где его подсмотрел. Но то что удобнее и выглядит эстетичнее -факт!
+1
классный тег ))))
сисек нет
puzzlesea, малодца!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.