Просмотр полной версии : влияет ли количество слушателей на производительность
random13
27.04.2010, 14:24
есть однотипные объекты расположенные на сцене, по клику, наведению на каждый происходят действия. Интересует вопрос производительности, что лучше повесить на родителя слушателя, ловить события проверять цель(target) и производить действия через публичные методы объекта, или же можно при создание объекта в нем определять слушателей которые бы выполняли всю работу без участия родителя?
производительности или скорости реакции на event ?
BlooDHounD
27.04.2010, 14:30
без участия родителя, действия Вам проводить те же самые. а на всплытие одного события тратиться не так уж много времени. то есть это время можно вообще не учитывать, так как событие будет пытаться всплыть всё равно, и не важно где оно найдёт слушателя, в родителе или в самом объекте. так что вы скорее потратите больше ресурсов на постоянные подписки и отписки.
Добавлено через 42 секунды
Crenth, это ваще бессмысленный вопрос =) скорость реакции будет одинакова в обоих случаях.
random13
27.04.2010, 14:35
мне просто важен момент связанный с расходом памяти, по поводу подписки отписки тут все просто стараюсь в каждом классе создавать метод зачищающий все слушатели перед его зануливанием.
почему спрашиваю: может быть такая ситуация что на экране появится около 500 объектов и вот тут и хотелось бы понять какой вариант выбрать?
Терминологически не согласен.
производительность - количество однотипных операций в единицу времени.
скорость реакции - интервал между событием и реакцией на него.
очень многое зависит от того, как реализованы внутренние механизмы FP.
Можно кривое всплытие написать. А можно криво написать обработку события родителя.
Рекомендую тупо проверить оба варианта, нагрузив ваше приложение. Теоретический ответ может дать только разработчик
random13
27.04.2010, 14:43
по поводу самого всплытия тут как раз мне кажется что производительность мало различима, она как я думаю зависит от вложенности объектов... а она не настолько глубока в любом из проектов
BlooDHounD
27.04.2010, 14:48
Crenth, рекомендую начать читать про специфику ФП. и не давать советов в область, в которой Вы ничего не понимаете.
random13, Вы внимательно прочитали мой пост?
BlooDHounD, у вас есть право забанить мои реплики в форуме. Однако, не нужно давать мне советы не по теме
random13
27.04.2010, 15:11
BlooDHounD, у вас есть право забанить мои реплики в форуме. Однако, не нужно давать мне советы не по теме
бррр грубо...
random13, Вы внимательно прочитали мой пост?
прочитал, короче как я понял Вы имеете ввиду что количество не повлияет, исключительно вопрос удобства работы и зачистки всего этого добра..? так?
orcpochta
27.04.2010, 15:15
без участия родителя, действия Вам проводить те же самые. а на всплытие одного события тратиться не так уж много времени. то есть это время можно вообще не учитывать, так как событие будет пытаться всплыть всё равно, и не важно где оно найдёт слушателя, в родителе или в самом объекте. так что вы скорее потратите больше ресурсов на постоянные подписки и отписки.
а меня вот смущает такое соображение, что если мы имеем 50-500 объектов в родителе, и на каждом висит слушатель, который занимает какую-то память, регистрируется в каких-то стеках вызовов, вероятно участвует еще в каких-то внутренних процессах - не слишком ли это расточительно по сравнению с тем, чтобы повесить один слушатель на родитель?
подписка делается ведь при создании каждого отдельного из кучи однотипных объектов ?
а отписка, соответственно, при уничтожении каждого.
не думаю, что с точки зрения объема исходного кода этот способ сложнее. он даже может оказаться гибче...
но выяснить ресурсоемкость первого и второго подходов можно только экспериментальным путем...
P.S. думаю, что "слушатель" представляет собой несколько байт и ни грамма исполняемого кода.
mickfallout
27.04.2010, 15:20
orcpochta, об этом BlooDHounD и говорит "вы скорее потратите больше ресурсов на постоянные подписки и отписки"
orcpochta
27.04.2010, 15:25
orcpochta, об этом BlooDHounD и говорит "вы скорее потратите больше ресурсов на постоянные подписки и отписки"
зачем подписки и отписки? предположим, мне надо, чтобы каждый объект что-то делал по событию ENTER_FRAME, все объекты у меня лежат в массиве (можно в векторе), слушатель повешен на родителя (или вообще на кого угодно - я создаю объект класса Shape, который обзываю pulsar - он у меня что-то типа тактового генератора в процессоре и он заставляет всех плясать), по событию родитель пробегается по массиву и у каждого члена вызывает, например, публичный метод onTact(), а какая ф-ия подставляется в этот метод в самом объекте - зависит уже от внутреннего состояния объекта.
random13
27.04.2010, 15:28
просто при этом тоже получается что наш объект не что то самостоятельное а очень сильно завязанное на внешнем поведение, или это есть хорошо?
orcpochta
27.04.2010, 15:35
просто при этом тоже получается что наш объект не что то самостоятельное а очень сильно завязанное на внешнем поведение, или это есть хорошо?
ровно на столько, на сколько завязан объект, слушающий событие, например, таймера или обновления экрана
я как-то испытывал эту схему еще в 8 флеше и у меня бодро бегало 50 на 50 танков (в смысле по 50 в двух командах) по клеткам не наезжая друг на друга и радостно друг-друга убивая с эффектом разлетающихся осколков
BlooDHounD
27.04.2010, 16:19
так ... из происходящего могу понять, что читать умеет только mickfallout.
1. баблинг происходит не зависимо от того, есть слушатели или нет.
2. когда генерируется событие ему всё равно придётся на каждом этапе всплытия проверить "а есть ли тут слушатель".
3. если у нас будет 500 вложенностей, то произойдёт 500 проверок для события. независимо от того на каком уровне вложенности Вы подпишитесь, все 500 проверок произойдут любом случаи.
исходя из этого на скорость обработки это никак не повлияет.
подписываясь у родителя, Вы делаете это один раз. создавая всего одного слушателя. подписываясь у каждого из детей, Вы создаёте N слушателей.соответственно вы тратите в N раз больше памяти и в N раз у вас будет медленнее инициализация прослушки.
orcpochta
27.04.2010, 16:22
имелось в виду 50-500 одноуровневых детей ессно)))
BlooDHounD
27.04.2010, 16:25
orcpochta, да это совершенно не важно, и к теме не относится.
orcpochta
27.04.2010, 16:31
как же не относится? дети есть, слушатели есть
BlooDHounD
27.04.2010, 16:49
повторюсь:так ... из происходящего могу понять, что читать умеет только mickfallout.
mickfallout
27.04.2010, 17:02
как же не относится? дети есть, слушатели есть
Структура вложенности не имеет значения для сравнения скорости способа "подписывать родителя" и способа "подписывать каждого ребёнка". В ЛЮБОМ случае событие будет всплывать от того объекта где произошло, до самого верха иерархии отображения. В ЛЮБОМ случае на каждом "этаже" оно будет смотреть, есть ли листнер. В ЛЮБОМ случае листнер выполнится один раз.
Затраты на всплытие, проверки наличие листнера будут одинаковы, надеюсь это понятно. отличатся будут только затраты подписки/отписки. при 50 объектах вы 50 раз подпишите каждого ребёнка или один раз - родителя. вне зависимости от того является ли отец "дедом", "прадедом" и т.п. =)
BlooDHounD
27.04.2010, 17:09
mickfallout, думаешь с 3го раза станет понятнее? :D
mickfallout
27.04.2010, 17:12
BlooDHounD, возможно =) в педагогике вроде считается что повторять надо 3 раза... =)
random13
27.04.2010, 17:28
повторение - мать утечения...))
семь раз прочти один раз напиши))
спасибо, вобщем ответили на вопрос и примерно логика ясна
Psycho Tiger
27.04.2010, 17:46
Только ещё момент есть: например, по клику если подписан лишь родитель, а нужно получить дитё, которое лежит под мышкой нужно провести какие-то операции, например getObjectsUnderPoint, и в итоге мы получаем доп. нагрузку (пусть и мизерную, в другом случае это может быть чуть более существенно) в момент исполнения программы. Затрачивая больше памяти и подписывая все N объектов на клик мы загружаем ЦП единожды, во время подписки, а по клику сразу имеем нужный объект.
Я к тому, что нужно по задаче больше смотреть. Я слабо представляю, но могу допустить ситуацию в котором при каждом движении мыши надо производить какие-то нечеловеческие калькуляции математикой, чтобы узнать кто лежит внизу и тогда, наверное, подписка каждого объекта была бы предпочительней
stopPropagation наше всё.
mickfallout
27.04.2010, 17:49
Только ещё момент есть: например, по клику если подписан лишь родитель, а нужно получить дитё, которое лежит под мышкой нужно провести какие-то операции, например getObjectsUnderPoint, и в итоге мы получаем доп. нагрузку (пусть и мизерную, в другом случае это может быть чуть более существенно)
Э... Можно по подробнее? "дитё" по которому кликнули хранится в currentTarget. Координаты клика - в event.stageX/Y. Какие вычисления?
BlooDHounD
27.04.2010, 18:06
mickfallout, видимо он бредит. просто он ничего не знает о event.target.
Psycho Tiger
27.04.2010, 18:10
в target, в currentTarget хранится тот, кого подписали на событие.
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class JustMain extends Sprite
{
public function JustMain()
{
super();
var spr:Sprite = new Sprite();
var spr2:Sprite = new Sprite();
var spr1:Sprite = new Sprite();
spr2.graphics.beginFill(23412343);
spr2.graphics.drawRect(0, 0, 100, 100);
spr2.graphics.endFill();
spr1.graphics.beginFill(23412343);
spr1.graphics.drawRect(0, 0, 100, 100);
spr1.graphics.endFill();
spr.addChild(spr2);
spr.addChild(spr1);
spr1.y = 200;
super.addChild(spr);
spr.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void
{
(e.currentTarget as Sprite).x += 10;
(e.target as Sprite).y += 10;
}
}
}
А по тому что ты сказал - да, ты прав. Туплю последнее время много...
mickfallout
27.04.2010, 18:13
в target, в currentTarget хранится тот, кого подписали на событие.
да, я "оговорился" =)
Я думаю, что не все так однозначно, т.как для проверки необходимости отправки события прийдется затратить больше усилий, елси мы будем делать "точный" хиттест (т.е. с шейп флагами), а, если, например, заранее извесно, что все дети - прямоугольники, то, возможно, что отключив им mouseEnabled, и сделав более простой хиттест, мы получим лучший результат, чем при всплытии... Кроме того, всплывающие события создаются по-новой, таким образом, мы рискуем нарваться на GC во время этого процесса - и, раз на десять весь процесс вцелом будет изза этого гораздо дольше.
BlooDHounD
27.04.2010, 18:49
чего чего про GC? не понял.
Psycho Tiger
27.04.2010, 18:58
Создавая новый объект мы рискуем вызвать GC, а он работает достаточно долго. Тем самым мы рискуем в какой-то момент времени сделать очень "дорогое" событие.
BlooDHounD
27.04.2010, 19:18
Psycho Tiger, создавая новый объект мы ничем не рискуем. и пока вызов стэка не завершиться никакой GC ничего убивать не будет. и уж тем более объект, который передаётся в параметре. все события в ФП вызываются синхронно, и вообще не понимаю как GC может вообще возникнуть в такой ситуации. это типа если бы я гулял по центральному парку Нью-Йорка, и тут на меня из-за одинокого дерева БелАЗ выезжает. вероятности приблизительно равны.
на сколько я себе представляю модель событий DOM (не на уровне АС3, а на уровне логики ее работы), каждый раз когда возникает событие, диспетчер строит цепочку от корня до цели (последней ветки) и работает только с этой цепочкой. Это подтверждает тот факт, что удаление или добавление слушателя в тот момент, когда событие уже произошло и обрабатывается, не влияет на результат обработки события.
И делаю вывод такой: скорость работы схемы с подпиской слушателя на каждый объект будет такой же, как и с подпиской на родителя. Однако, она будет быстрее, чем если подписывается не родитель, а дед или прадед.
BlooDHounD
27.04.2010, 19:47
И делаю вывод такой: скорость работы схемы с подпиской слушателя на каждый объект будет такой же, как и с подпиской на родителя. Однако, она будет быстрее, чем если подписывается не родитель, а дед или прадед.скажите пожалуйста, чем выделенная часть утверждения отличается по логике работы первой его половины?
веток больше, проход от корня к цели дольше. чо тут не понятно ?
arkadattx
27.04.2010, 20:10
Извиняюсь, что встреваю, но ни у кого нет желания провести парочку тестов? А то я за этой темы слежу с момента ее создания, а времени с того момента прошло уже достаточно, а пока чуть ли не холивар...
Сделал бы и сам, но боюсь что мой код поднимут на смех...
Psycho Tiger
27.04.2010, 20:11
Psycho Tiger, создавая новый объект мы ничем не рискуем. и пока вызов стэка не завершиться никакой GC ничего убивать не будет. и уж тем более объект, который передаётся в параметре. все события в ФП вызываются синхронно, и вообще не понимаю как GC может вообще возникнуть в такой ситуации. это типа если бы я гулял по центральному парку Нью-Йорка, и тут на меня из-за одинокого дерева БелАЗ выезжает. вероятности приблизительно равны.
Объект в параметре тут не причем. Речь шла о лёгком лаге.
Короче говоря:
...
var i:uint=1000000;
while (i--) new Object();
...
//конец стека вызовов
//тут вызывается GC, собирая весь мусор.
В итоге, если GC не вызывается с таким кодом мы имеем стабильно, например, 30 фпс. Когда он вызовется GC фпс единожды упадет до 30-n, до следующего вызова GC.
BlooDHounD
27.04.2010, 20:33
Crenth, а Вы о том, что чем ниже к предок тем позже вызовится событие? спасибо, КО. Вы не поверите, но именно в этом суть баблинга. было бы стрёмно, если бы события предков вызывались в вперемешку =) и разница в отклике в пару наносекунд, я думаю никого не волнует.
Psycho Tiger, а зачем Вы там будите вызывать GC?
Psycho Tiger
27.04.2010, 20:41
Я не буду вызывать, он сам =). wxvxw об этом и писал:
Кроме того, всплывающие события создаются по-новой, таким образом, мы рискуем нарваться на GC во время этого процесса - и, раз на десять весь процесс вцелом будет изза этого гораздо дольше.
Не во время, конечно, но после конца стека вызовов есть шанс, что GC сработает, потому что он так решит, что вызовет лаг.
BlooDHounD
27.04.2010, 21:06
Psycho Tiger, пока все дейсвия в стэке не завершаться GC не запутится. а между стэками ... ну вызовется и вызовется. это его работа =) и причём тут лаг? лаг возникает как раз тогда, когда выгружать надо килограммы памяти. а не копейки.
Psycho Tiger
27.04.2010, 21:48
Ну да, прав. Хотя если по событию вроде MOUSE_MOVE "всплывать" событие и постоянно теребить мышкой - в принципе можно эти килограммы памяти и получить. Один хрен смотреть надо по ситуации.
Вообще я никогда не сталкивался с проблемой GC, проблему нафантазировал с подачи wxvxw чтобы в будущем знать, что делать. Видимо, проблема высосана из пальца. Спасибо.
gloomyBrain
27.04.2010, 22:29
роблему нафантазировал с подачи wxvxw чтобы в будущем знать, что делать. Видимо, проблема высосана из пальца. Спасибо.
Ну, почти отмазался =)
Psycho Tiger
27.04.2010, 22:44
А толку мазаться? Если я в каких-то суждениях заблуждаюсь и мне об этом говорят - это очень хорошо.
BlooDHounD
27.04.2010, 23:06
Psycho Tiger, чего? от чего там появятся килограммы памяти? сейчас они у вас появляются от того, что Вы мышкой теребите? если Вы думаете, что event.clone вызывается постоянно, даже если нету слушателя, то Вы глубоко заблуждаетесь. это было бы просто глупо. и если бы было так, то GC был бы Вашим лучшим другом, Вы бы с ним не расставались.
Psycho Tiger, создавая новый объект мы ничем не рискуем. и пока вызов стэка не завершиться никакой GC ничего убивать не будет. и уж тем более объект, который передаётся в параметре. все события в ФП вызываются синхронно, и вообще не понимаю как GC может вообще возникнуть в такой ситуации. это типа если бы я гулял по центральному парку Нью-Йорка, и тут на меня из-за одинокого дерева БелАЗ выезжает. вероятности приблизительно равны.
А какая разница когда? от того, что лаг будет не сию секунду, а через полсекунды тебе легче станет? Лаг то все равно будет.
И да, GC вполне может включится если будет много событий диспатчится и соответственно удалятся - от чего бы не включится, их же кто-то должен убирать?
Т.е. традиционно, большую часть времени занимает отрисовка (а не наши банальные скрипты), но если изза сборщика мусора ты не успел к плановому апдейту - ты увидишь лаг, т.е. если в это время играет какая-то анимация, то она тормознет.
Да и вообще, не об этом была речь, даже если предположить, что сборщик мусора работает очень быстро, то вполне есть шанс, что в определенной ситуации можно придумать решение которое будет более еффективным чем "точный" хиттест который должен сделать плеер, чтобы определить диспатчить ли событие кому-то или нет. Как я уже говорил, если хиттестить надо квадратики, или заведомо не пересекающиеся фигуры или круги, то тут просто напрашивается не подписываться на всплытие, а выявление цели (целей) использовав упрощенный алгоритм.
Psycho Tiger
27.04.2010, 23:33
Да, wvxvw сказал сейчас примерно мои мысли =)
BlooDHounD, насколько мне известно GC не убирается по мелочам, она ленива. Пусть минуту не будет лага, но потом когда события наплодят килограмм она включится лаг будет.
Вообще уже считаю что разговор идёт в тупик. Надо всегда смотреть по ситуации и не иметь шаблонов в голове.
BlooDHounD
27.04.2010, 23:37
Олег, я могу тебя расстроить. ссылки на локальные переменные удаляются сразу же. без всяких GC. так что от тупой генерации событий GC не запуститься.
Psycho Tiger, уу-к. покажи мне этого сферического коня в вакууме.
А при чем тут теплое с мягким? Представь, что событие в памяти не занимает место кратное 8, 256 или 1024 или не знаю, как там у нас память распеделяется - это значит, что память будет фрагментироваться не зависимо от того, когда именно ты удалил объект, а самая большая нагрузка - это не вычистить, а переназначить / дефрагментировать память. Т.е. забить массив нулями это одно, а найти части массива, которые бы можно было поместить между другими частями займет гораздо больше циклов. Кроме того, речь вообще о другом.
GC умеет дефрагментировать память? Где об этом можно подробнее узнать?
Нет, это не задача GC, но эти процессы не могуть быть не связаны, т.как если GC высвобождает память, то если у нас все объекты не одинакового размера, то рано или поздно наступит момент, когда количество "дырок" т.е. неиспользуемых участков памяти будет очень большим. Легче всего это представить, как тетрис :) GC это когда вы заполнили ряд, a фрагментация, это когда в ряду остались "дырки".
Я чесно не знаю, как именно флеш дефрагментирует свою память, но если бы он этого не делал вообще, то любая флешка запущенная долгое время отъедала бы все больше и больше ресурсов. И в итоге флеш не любили бы еще больше :)
BlooDHounD
28.04.2010, 01:33
wvxvw, а зачем делать то, что ты описываешь? есть специальные блоки памяти, под разные объекты. локальные переменные хранить не надо. и у удалять не особо надо. можно поверх писать и не парится. всё равно к ним повторного обращения не будет.
Добавлено через 2 минуты
это блоки довольно большие кстати. оченб большие. и динамически выделяются постоянно. чистить их нет смысла, ибо если один раз засрались, то существует вероятность, что и второй раз засруться. действия в приложении в основном циклические.
Добавлено через 3 минуты
именно поэтому, кстати, наблюдается постепенный рост используемой памяти.
Я вообще про другое...
Т.как я не особо силен в этом вопросе, и то, как именно плеер распоряжается своей памятью покрыто мраком, я бы наверное почитал вот это:
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
Скажем так, вряд ли человечество придумало что-то радикально новое и не похожее. Возможно, что в плеере эти проблемы решаются по-другому, но они все-равно должны как то решаться. Можно еще погуглить про Яву молодое поколение vs старшее поколение, в Яве как-то этот вопрос более освещен, потому что на ней есть много серверов, где за память нужно очень усердно бороться :)
Если наблюдается постоянный рост памяти - то это плохо :( Но, как бы это по-моему не впервой такое с плеером... как бы не привыкать.
BlooDHounD
28.04.2010, 03:39
я прекрасно понимаю о чём ты говоришь. просто все объекты в ВМ деляться на 2 типа, который нужно сохранить, и который можно сразу выбросить. так вот локальные переменные относятся ко второй категории. это память никак не чиститься. ибо она всегда засрана.
Нет, локальные переменные как раз не могут к ним относится - почитай статью, там все хорошо расписано, локальные переменные, это как раз одни из "корневых" ссылок от которых начинается отсчет других ссылок.
Если бы это было не так, то ты бы просто ничего не смог написать вообще, как только первая запущенная функция (конструктор документ класса) отработала бы, на этом вся твоя програма и закончилась бы.
Every application has a set of roots. Roots identify storage locations, which refer to objects on the managed heap or to objects that are set to null. For example, all the global and static object pointers in an application are considered part of the application's roots. In addition, any local variable/parameter object pointers on a thread's stack are considered part of the application's roots. Finally, any CPU registers containing pointers to objects in the managed heap are also considered part of the application's roots. The list of active roots is maintained by the just-in-time (JIT) compiler and common language runtime, and is made accessible to the garbage collector's algorithm.
Смотри, я не говорю, что у нас должно быть один-в-один с .NET, но по духу и по принципу работы AVMPlus это игрушечная копия CLR, т.е. скорее всего, что у нас все проще, и финализация не имеет к нам никакого отношения, но принципиально должно быть похоже. В Яве примерно тоже так...
BlooDHounD
28.04.2010, 11:51
не, меня не хватит на столько английского за раз. но из твоего абзаца ничего не ясно. и не ясно зачем локальным переменным быть корнем приложения. спорить о прозрачности воздуха мне надоело, так, что давай закруглимся. то есть я пониманию, что ты хотел донести до меня, но моё сознание пока не готово принять всё за чистую монету.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.