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

Собственно код:
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, малодца!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.