Просмотр полной версии : Вопрос: удаление всех Child из родительского мувика.
Перевожу прогу AS2->AS3.
Проблема:
Есть top:MovieClip - родительский.
В нем создаю через new MovieClip и addChild еще мувики (программно создаю).
Есть кнопка очистки родительского мувика. Алгоритм чистки следующий:
function clearTop(){
for(var i:Number = 1; i<=top.numChildren; i++){
if(top.getChildAt(i)){
top.removeChildAt(i);
}
}
}
Алгоритм работает один раз - чистит содержимое top, а на второй раз - ругается что нет нифига - ругается 2006 ошибкой, типа нет мувика с таким индексом. Хотя проверку я поставил.
Как сделать корректную проверку на существование Child?
Замена top.getChildAt(i) на Boolean(top.getChildAt(i)) - ничего не дала
BlooDHounD
04.03.2008, 13:52
Ошибки:
1. индексы детей начинаются с 0.
2. if(top.getChildAt(i)){
top.removeChildAt(i);
}код бесмысленен. в АС3 не бывает пустых пространств между детьми. удаляя одно дитя, все кто сидел выше смещаются вниз.
3. for(var i:Number = 1; i<=top.numChildren; i++){...по причине описанный в п.2, у вас вообще получается обсурд. с каждым удалёнием numChildren уменьшается на 1. и при этом вы удаляете i-тый элемент.
вот ваш алгаритм:
start. 1. 2. 3.
0 - A 0 - A 0 - A 0 - A
1 - B 1 - C 1 - C 1 - C
2 - C 2 - D 2 - E 2 - E
3 - D 3 - E 3 - F
4 - E 4 - F
5 - F
Обалдеть! А как тогда правильно удалить всех детей родительского мува?
Mr. Fixit
04.03.2008, 15:00
или так:
while(this.numChildern > 0) this.removeChildAt(0);
или так:
for(var i : int = 0; i < this.numChildern; i++) this.removeChildAt(0);
или так:
for(var i : int = this.numChildern-1; i >= 0 ; i--) this.removeChildAt(this.numChildern-1);
или еще как-то :D
BlooDHounD
04.03.2008, 15:03
или так:var num:int = super.numChildren;
while ((num -= 1)>0) super.removeChildAt(num);
Парни! Идеально! Спасибо!!
Недопетривал стековость контейнера. Теперь вообще многое прояснилось)))
Бармалей
04.03.2008, 16:46
Маленькая лепта от меня:
while (container.numChildren)
container.removeChildAt(container.numChildren - 1);
Удалять элементы с нулевой глубины - труднозатратно, поскольку элементы следующие за удаленным будут сдвинуты на единицу вниз. Представьте, если в контейнере содержатся несколько тысяч чайлдов.
BlooDHounD
04.03.2008, 17:17
ну если на то пошло то numChildren тоже жрёт ресурсы.
Бармалей
04.03.2008, 17:33
Ну я не спорю, только почему-то мне кажется, что numChildren кэшируется при изменении количества детей и возвращается по требованию, а не пересчитывается каждый раз при обращении к нему. ;-)
_Smirnoff
04.03.2008, 17:48
Узнайте кол-во детей один раз...и удаляйте относительно него + лучше удалать, начиная с верхних, чтоб не менять индексы слоев при удалении.
BlooDHounD
04.03.2008, 17:52
Ну я не спорю, только почему-то мне кажется, что numChildren кэшируется при изменении количества детей и возвращается по требованию, а не пересчитывается каждый раз при обращении к нему. ;-)ага ... может конечно и не считает, но скорости постоянное обращение к гетору не прибовляет. это таже история что и length у массива.
Бармалей
04.03.2008, 18:22
ага ... может конечно и не считает, но скорости постоянное обращение к гетору не прибовляет. это таже история что и length у массива.
Хорошо, дубль два в три строки:
var num:uint = container.numChildren;
while(num--)
container.removeChildAt(num);
=)
BlooDHounD
04.03.2008, 18:28
-- работает гараздо медлее чем -=. и теперь глянь на код, который я написал
Бармалей
04.03.2008, 18:54
-- работает гараздо медлее чем -=. и теперь глянь на код, который я написал
Рабочая машина. Flash Player WIN 9,0,115,0. Импорты пропущены.
Обратный инкремент с автоматическим приведением типов:
var t:int = getTimer();
var i:uint = 10000000;
while(i--){}
trace(getTimer() - t); // 181
Оператор вычитания с присваиванием и явным приведением типов:
var t:int = getTimer();
var i:uint = 10000000;
while((i -= 1)>0){}
trace(getTimer() - t); // 235
Статья годовалой давности про медленный инкремент (http://as3.ru/?p=5) видимо уже не актуальна в последних сборках проигрывателя. Хотя проигрыш в 54 миллисекунды при обсчете 10 миллионов операций не будет особенно заметен - основное время будет тратиться именно на очистку дисплей листа виртуальной машиной. Но "дубль два" все таки рулит. =)
BlooDHounD
04.03.2008, 19:12
и что? это доказывает мою правоту.
Бармалей
04.03.2008, 19:15
Почему? Наоборот: предложенный мной вариант выполнился за 181 миллисекунду, а предложенный тобой - за 235.
Azim, отредактируйте свой первый пост и оформите код тегами .
з.Ы.
var t:int = getTimer();
var i:uint;
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 235
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 56
Бармалей
04.03.2008, 20:07
Выносим инициализацию переменной i до таймера, и видим немного другие результаты =)
var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 41
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 41
BlooDHounD, Бармалей: вы потратили машинного времени на обсуждение этой ерунды больше, чем все флэшеры мира сэкономят на таких итерациях за последующие 50 лет.
Бармалей
04.03.2008, 20:16
BlooDHounD, Бармалей: вы потратили машинного времени на обсуждение этой ерунды больше, чем все флэшеры мира сэкономят на таких итерациях за последующие 50 лет.
Iv, зато теперь мы знаем Кунг-Фу на AS3. =)
Выносим инициализацию переменной i до таймера, и видим немного другие результаты =)
var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 41
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 41
Запустил код, у меня выдало:
//200
//54
соответственно
Еще не совсем понял из каких соображений переменная i типа uint, а не int. Для int у меня выдало:
//66
//48
WindWalker
04.03.2008, 22:08
запустил код, у меня выдало
200
54
соответственно
Добавьте ещё в конце:
trace (flash.system.Capabilities.version);
Подозреваю, что выдаст 9,0,45,0
Выносим инициализацию переменной i до таймера, и видим немного другие результаты =)
var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
trace(getTimer() - t); // 41
t = getTimer();
for (i = 10000000;i>0;i-=1){};
trace(getTimer() - t); // 41
У тебя, значит, уникальный флеш, потому как проверил, для чистоты эксперимернта:
http://img232.**************/img232/7006/speeded9.png
txt.text = Capabilities.version+"\n";
var i:uint;
var t:int = getTimer();
for (i = 10000000;i>0;i--){};
txt.appendText((getTimer() - t)+"\n");
t = getTimer();
for (i = 10000000;i>0;i-=1){};
txt.appendText((getTimer() - t)+"\n");
badun, uint из простых соображений, что с числами меньше нуля мы не работаем в цикле.
Бармалей
05.03.2008, 00:59
Я заметил только, что имеет значение очередность работы циклов. Если поменять блоки циклов местами, то вот что получится (http://yarovoy.com/temp/test_reverse.png). Хотя, если ничего не трогать, то будет вот так (http://yarovoy.com/temp/test.png). Предыдущие указанные мною значения были получены при тестировании в FlashDevelop на рабочем компе.
to __etc
Так int же не обязывает использовать отрицательные значения. Просто тут обсуждение перешло в область оптимизации, а то что int шустрее чем uint вроде как давно известно. По-этому и не понял зачем оно тут, тем более, что numChildren типа int.
Я заметил только, что имеет значение очередность работы циклов. Если поменять блоки циклов местами, то вот что получится (http://yarovoy.com/temp/test_reverse.png). Хотя, если ничего не трогать, то будет вот так (http://yarovoy.com/temp/test.png).
Может это не от очередности зависит, а просто расхождения при каждом запуске? Если ничего не менять, значения останутся теми же?
Бармалей
05.03.2008, 01:09
В смысле ничего не менять? А как же тогда показать, что первый цикл выполняется медленнее, чем идущий за ним? =)
коряво выразился ))
в смысле ничего не менять, и несколько раз запустить и посмотреть какие значения будут выдаваться. Может там +-20 разброс )).
Я заметил только, что имеет значение очередность работы циклов.
Поменял местами :)
У меня тенденция не меняется, хоть в разных местах циклы поставь, декремент -=1 всегда быстрее --. Причем разница ощутимая:
http://img216.**************/img216/1510/speedum8.png
Бармалей
05.03.2008, 15:46
Давайте устроим массовую проверку. Вот swf-ка (http://yarovoy.com/temp/test.swf), скомпилированная при помощи Flex 3 SDK. А вот содержимого ее главного класса:
package
{
import flash.display.Sprite;
import flash.text.TextField;
import flash.utils.getTimer;
import flash.system.Capabilities;
public class Main extends flash.display.Sprite
{
protected var textField:TextField;
public function Main():void
{
textField = new TextField();
addChild(textField);
textField.text = Capabilities.version + "\n";
var i:uint;
var t:int;
t = getTimer();
for (i = 10000000;i>0;i--){};
textField.appendText((getTimer() - t) + "\n");
t = getTimer();
for (i = 10000000;i>0;i-=1){};
textField.appendText((getTimer() - t) + "\n");
}
}
}
А вот код этого же класса, восстановленный декомпилятором из swf:
package
{
import Main.*;
import flash.display.*;
import flash.system.*;
import flash.text.*;
import flash.utils.*;
public class Main extends Sprite
{
var textField:TextField;
public function Main() : void
{
1 0 211 1 22 var _loc_1:uint;
var _loc_2:int;
textField = new TextField();
addChild(textField);
textField.text = Capabilities.version + "\n";
_loc_2 = getTimer();
_loc_1 = 10000000;
while (_loc_1-- > 0)
{
// label
}
textField.appendText(getTimer() - _loc_2 + "\n");
_loc_2 = getTimer();
_loc_1 = 10000000;
while (_loc_1-- > 0)
{
// label
}
textField.appendText(getTimer() - _loc_2 + "\n");
return;
}
}
}
Итак, у кого какие значения появляются в текстовом поле при запуске swf. У меня:
WIN 9,0,115,0
38
38
Весьма вероятно, что конструкции i-=1 и i-- компилируются mxmlc, входящим в состав Flex 3 SDK в идентичный байткод. Кстати на днях вышла новая версия Sothink SWF Decompiler, позволяющая декомпилить АС3 код.
Значит это особенности компилятора CS3. Вне зависимости от этого, лучше использовать декремент с числом, дабы не получать неожиданных результатов.
Повод для размышлений:
package {
import flash.display.Sprite;
import flash.system.Capabilities;
import flash.text.TextField;
import flash.utils.getTimer;
public class Main extends Sprite {
private var textField:TextField;
public var i:uint;
public function Main() {
super();
textField = new TextField();
addChild(textField);
textField.text = Capabilities.version + "\n";
var t:int;
t = getTimer();
for (i = 10000000;i>0;i-=1){};
textField.appendText((getTimer() - t) + "\n");
t = getTimer();
for (i = 10000000;i>0;i--){};
textField.appendText((getTimer() - t) + "\n");
}
}
}
_Smirnoff
05.03.2008, 18:19
WIN 9,0,115,0
39
45
result такой
Mr. Fixit
05.03.2008, 20:45
незабывайте что:
...
for (i = 10000000;i>0;i-=1){};
textField.appendText((getTimer() - t) + "\n");
t = getTimer();
for (i = 10000000;i>0;i--){};
textField.appendText((getTimer() - t) + "\n");
...
сразу тестить не желательно.. поотдельности даёт более правильный результат.
незабывайте что:
...
for (i = 10000000;i>0;i-=1){};
textField.appendText((getTimer() - t) + "\n");
t = getTimer();
for (i = 10000000;i>0;i--){};
textField.appendText((getTimer() - t) + "\n");
...
сразу тестить не желательно.. поотдельности даёт более правильный результат.
Прежде всего надо знать, во что сей код превращается в CS3.
http://etcs.ru/blog/as3/slow_increment_ii/
Mr. Fixit
05.03.2008, 22:32
а причем тут это?
я говорю, что ты сразу считаешь циклы.. потому и нагрузка больше на последний цикл. Проверка циклов поотдельности даст более точный результат, что лучше. Да математика вся не во флеше, а в процессоре.
WindWalker
05.03.2008, 22:53
Предполагаю, что инкремент/декремент поля через ++ и -- превращается примерно в такой байткод:
1. взять поле i
2. увеличить
3. записать в поле i
4. взять поле i
И вот этот самый четвёртый пункт всё и портит.
BlooDHounD
05.03.2008, 23:23
о, госпади! спаси души этих еретиков!
WindWalker
05.03.2008, 23:32
Вот так выглядит i++, если i - это поле:
findpropstrict i
dup
setlocal1
getproperty i
increment
setlocal2
getlocal1
getlocal2
setproperty i
kill 2
kill 1
А вот так выглядит i+=1:
findproperty i
getlex i
pushbyte 1
add
initproperty i
То есть моё предположение оказалось неверным. Однако лишние манипуляции легко заметны.
Однако лишние манипуляции легко заметны.
Само собой, что заметны.
В общем, все всё выяснили, я думаю, вопросов больше возникать не должно.
з.Ы. Походу я отстал от жизни, раз пользуюсь собственным декомпилятором и не знаю о уже существующих :(
WindWalker
06.03.2008, 00:13
Дык это ж abcdump. В своё время по блогам пролетела целая волна постов про него.
А началось всё с того, что его кто-то раскопал в исходниках Тамарина.
Кстати, написан на AS3 :)
Дык это ж abcdump. В своё время по блогам пролетела целая волна постов про него.
А началось всё с того, что его кто-то раскопал в исходниках Тамарина.
Кстати, написан на AS3 :)
abcdump появился в июле 2007, когда уже был AVM2 Overview от Adobe. Я-то думал, речь идет о чем-нибудь посовременнее. Впрочем, это выходит за рамки темы и вообще неважно.
BlooDHounD
06.03.2008, 01:38
написан не на АС3, а на EcmaScript. они похоже, но не идентичны.
Бармалей
06.03.2008, 18:22
Вот так выглядит i++, если i - это поле:
findpropstrict i
dup
setlocal1
getproperty i
increment
setlocal2
getlocal1
getlocal2
setproperty i
kill 2
kill 1
А вот так выглядит i+=1:
findproperty i
getlex i
pushbyte 1
add
initproperty i
То есть моё предположение оказалось неверным. Однако лишние манипуляции легко заметны.
Откуда эти данные?
BlooDHounD
06.03.2008, 18:36
байткод. что ту не понятного? мы сидим и целыми днями фигачим декомпилятор, мы всё знаем :)
Откуда эти данные?
Это в случае поля i класса.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.