Профилирование Flex - что делает [enterFrameEvent]?

Мне было поручено найти (и, возможно, исправить) некоторые серьезные проблемы с производительностью в доставленном нам приложении Flex. Приложение будет постоянно занимать от 50 до 100% ЦП в то время, когда оно просто простаивает и не должно ничего делать.

Моим первым шагом было запустить профилировщик, поставляемый с FlexBuilder. Я ожидал найти какой-нибудь метод, который занимал большую часть времени, показывая мне, где было узкое место. Однако я получил кое-что неожиданное.

Четыре лучших метода:

  • [enterFrameEvent] - 84% кумулятивно, 32% самостоятельно
  • [reap] - 20% кумулятивного и самостоятельного времени
  • [tincan] - 8% совокупного и самостоятельного времени
  • global.isNaN - 4% совокупного и самостоятельного времени

У всех других методов было менее 1% как для совокупного, так и для собственного времени.

Из того, что я нашел в Интернете, [заключенные в скобки методы] - это то, что перечисляет профилировщик, когда у него нет реального метода Flex для отображения. Я видел, как кто-то утверждал, что [tincan] - это обработка запросов RTMP, и я предполагаю, что [reap] - это сборщик мусора.

Кто-нибудь знает, что на самом деле делает [enterFrameEvent]? Я предполагаю, что это, по сути, «основная» функция для цикла событий, поэтому ожидается большое совокупное время. Но почему время для себя так велико? Что на самом деле происходит? Я не ожидал, что внутренние компоненты плеера займут так много времени, тем более что в приложении на самом деле ничего не происходит (и обновлений пользовательского интерфейса не происходит).

Есть ли хороший способ разобраться в том, что происходит? Я знаю, что происходит что-то, чего не должно быть (похоже, должно быть какое-то занятое ожидание или другой цикл выхода из-под контроля), но профилировщик не дает мне никаких результатов, которых я ожидал . Следующим моим шагом будет добавление операторов трассировки отладки в различных местах, чтобы попытаться отследить, что на самом деле происходит, но я чувствую, что должен быть способ лучше.


person Herms    schedule 03.12.2008    source источник


Ответы (7)


Есть пара вещей, которые обычно происходят с обработчиком энтерфрейма в гибком проекте. Некоторые вещи, на которые стоит обратить внимание

  1. Вручную ‹mycomponent enterFrame =" "> ответы на события или добавленные вручную через component.addEventListener (Event.ENTER_FRAME, myfunc)

  2. callLater (), они происходят ВСЕГДА в структуре и могут быть побочным продуктом прыжка через любое количество кроличьих нор, разработчики часто используют их для решения проблем, связанных с синхронизацией, а иногда плохой код может заставить их продолжать вызывать каждый кадр. Например, в последней сборке flex sdk есть ~ 120 вхождений calllater ().

  3. наконец, я не могу гарантировать, что [enterframeEvent] обрабатывает только обратные вызовы событий определенного кадра, а не события таймеров, мыши и т. д., поскольку кадры ввода возникают во время цикла основного события, вы можете увидеть совокупный результат всех запускаемых событий из основного пула событий. Я не говорю, что это происходит, но я не могу сказать, что это НЕ то, что происходит, я недостаточно знаю о внутреннем устройстве, чтобы быть уверенным.

/ edit также, как указывалось ранее, [enterFrameEvent] технически должен срабатывать изнутри в начале каждого кадра, но он не должен ничего делать, если только события не были явно привязаны к нему для выполнения пользовательского кода.

person seanalltogether    schedule 08.12.2008
comment
Но любые методы, переданные callLater или добавленные в качестве слушателей, должны отображаться в профилировщике, не так ли? Поскольку это будут настоящие методы AS3, я ожидаю, что время будет отображаться в этих методах, а не в самом enterFrameEvent. Вот что странно. - person Herms; 09.12.2008
comment
Да и нет, enterframeEvent будет совокупностью всего, что происходит, если бы у вас было 10 или 20 обратных вызовов, обрабатываемых во время этого события, все они могли бы быть незначительными и не регистрироваться в профилировщике по отдельности, но вместе они представляют собой много времени. - person seanalltogether; 10.12.2008
comment
Профайлер показывает 2 статистики. Накопительный и самостоятельный. Кумулятивная - это то, о чем вы говорите. Я считаю, что «Я» - это то, сколько времени тратится именно на этот метод, а не на другие профилированные методы. - person Herms; 11.12.2008
comment
Нет, когда я имею в виду совокупное, я имею в виду все, что происходит в этой отправке. Если у вас есть functionA и functionB, а A вызывает B в пределах своей области, тогда время для A будет включать время для B, они не разделены. Точно так же события содержат время всех функций, которым они отправляются. - person seanalltogether; 12.12.2008
comment
Кумулятивная и Самостоятельная в профилировщике должны относиться ко времени на протяжении всего приложения (кумулятивно) по сравнению со временем, потраченным во время моментального снимка (собственное). - person seanalltogether; 12.12.2008

Некоторые обновления: мы ничего не делаем в приложении, кроме прослушивания событий и использования привязок ... то есть без ChangeWatcher, без ручного опроса ... просто ждем событий. Мы постоянно подключены к FMS, поэтому накладные расходы на это есть, но они минимальны. Привязки не очень эффективны в Flex, и мы обнаружили, что нецелесообразно добавлять ключевое слово метаданных [Bindable] непосредственно в классы (в большом объеме, с большим количеством классов). Мы мало этим занимаемся, но это один из способов выжать из вашего приложения немного больше производительности. Если вы используете [Bindable (event = "usersUpdated")], тогда у вас есть контроль над привязкой, и она будет срабатывать только тогда, когда вы отправляете событие dispatchEvent (new Event ("usersUpdated")) из функции в классе, т. Е. сеттер для "пользователей".

Любой, кто использовал System.gc () в Flex или AIR, скажет вам, что сборка мусора Flex - это шутка. Это частично реализованная функция, и никто ей не доверяет. Для этого тоже есть уловки ... вызовите его дважды, подождите кадра, вызовите снова. Он может очистить ваши старые предметы, но не скрещивайте пальцы ... Flex делает то, что хочет.

Также используйте временные объекты, чтобы уменьшить количество срабатывающих привязок. Вместо...

myUser.location = новое местоположение (); myUser.location.state = "CO"; myUser.location.city = "Денвер";

do...

var tempLoc: Location = новое местоположение (); tempLoc.state = "CO"; tempLoc.city = "Денвер"; myUser.location = tempLoc;

Первый запускает 3 привязки к чему-либо, привязанному к location. *, В то время как последний должен запускать только 1 привязку (на самом деле это обычно дополнительно из-за того, как Flex обрабатывает это).

Привязки не убьют ваше приложение, пока их не будет много в визуально насыщенном приложении .... привязка и рендеринг кажутся самыми медленными задачами Flex.

Еще одна интересная вещь: создайте новое приложение Flex3 в Flex Builder и запустите его в браузере. Наши тесты показали, что ЦП на MacBookPro остается в пределах 8-10% (когда приложение неактивно и окно браузера скрыто). Наше приложение теперь стабильно работает на ~ 20%, и, хотя оно резко увеличивается для обработки изменений представления и т.п., оно всегда возвращается к уровню, близкому к 20%. Наша первоначальная проблема заключалась в том, что произошла утечка памяти или что-то убегающее, что привело бы к очень высокой загрузке ЦП и оставлению его на уровне около 40-50% (опять же, на MBP ... все относительно этой машины). Мы удалили все ссылки на Degrafa, и, хотя мы заметили небольшое увеличение производительности, это не все. Тем не менее, пустое приложение Flex было поучительным - сам Flex постоянно загружает процессор на 8-10%, даже когда он простаивает.

Еще одна находка ... при использовании Mate будьте осторожны при переключении представлений. Легко иметь доступные ресурсы и просто скрывать и отключать их, когда они не используются, с помощью инжектора и привязки в MXML, но Flex не очень умен, когда дело доходит до скрытия / отключения вещей. Лучше всего создавать виды на лету и уничтожать их, когда они будут готовы. Несмотря на то, что первоначальное создание может занять больше времени и между представлениями будет более длительное ожидание, используйте некоторую магию отображения (индикатор выполнения, вращающийся диск и т. Д.), Чтобы указать, что представление переключается, дождитесь завершения создания в представлении, а затем раствориться в нем.

Также держитесь подальше от ViewStack для визуально насыщенных приложений. Управляйте своим собственным стеком.

До сих пор в этой ветке обсуждались основные проблемы производительности, общие для любого языка, но Flex - особенный мальчик во многих отношениях («особенный» не всегда считается положительным моментом). Существует бесчисленное количество подводных камней, поскольку он построен на очень визуальной платформе, но при этом построен для RIA, поэтому, хотя Flash Player может оптимизировать видео, анимацию и т. Д., Он не будет оптимизировать приложение Flex. Не ожидайте, что приложения Flex будут работать так же, как приложения Flash. Также существует большая разница между AVM (виртуальная машина ActionScript) для AS2 и AS3.

Это просто поверхностный обзор проблем с производительностью и потенциальных преимуществ приложений Flex. Это темное искусство, и легко понять, почему.

Используйте, ниндзя.

person Community    schedule 05.12.2008
comment
Просто к сведению: пустое приложение Flex на моей машине постоянно работает с 0% ЦП. Позже я собираюсь протестировать его на дрянной старой коробке, чтобы увидеть, не изменится ли он. Поэтому я не думаю, что это особенно полезно, поскольку проблемы с производительностью, которые у нас есть в приложении, также связаны с Windows. - person Herms; 06.12.2008

Обновление этого сообщения, если кто-нибудь столкнется с ним в будущем ...

Через пару месяцев у нескольких сотрудников EffectiveUI возникла именно эта проблема со своим приложением, поэтому к ней вернулись. Было обнаружено, что при использовании Flash для создания визуальных ресурсов, ИСПОЛЬЗОВАНИИ СТАТИЧЕСКИХ СКИНОВ и их экспорте в SWC с помощью набора инструментов Flash / Flex вы получаете неконтролируемые Flash-ролики (предположительно, что-то внутреннее по отношению к способу его реализации, например, забывая указать stop () в кадрах).

По-видимому, вы ничего не можете с этим поделать, кроме как зайти и удалить все скины с отслеживанием состояния. Хорошее описание можно найти здесь:

http://patrickhansen.com/blog/index.php/2009/03/05/flex-stateful-skins-vs-stateless?blog=3

И сценарий JSFL, который можно использовать для преобразования скинов с сохранением состояния в скины без сохранения состояния:

http://patrickhansen.com/blog/index.php/2009/04/08/stateful-to-stateless-jsfl-flash-command?blog=3

Надеюсь, это кому-то поможет! Это очень неприятная и загадочная ошибка, но ее можно обойти!

Ваше здоровье

person Community    schedule 16.04.2009

Я думаю, твоя проблема в другом. Это происходит потому, что Flex построен на основе Flash, и Flash запускает это событие так часто, как частота кадров (примерно 20–30 раз в секунду).

http://www.adobe.com/support/flash/action_scripts/actionscript_dictionary/actionscript_dictionary546.html

РЕДАКТИРОВАТЬ: Я не говорю, что ваше решение - снизить частоту кадров. Это сработало бы, только если бы проблема была в событии, которое вы заметили. Я не уверен, что именно это и вызывает у вас замедление. Это может быть вызов функции, которая вызывает проблему ... но это не само событие. Он должен много стрелять.

person Justin Bozonier    schedule 04.12.2008
comment
Я попытался поиграть с частотой кадров, но на производительность это не повлияло. Слишком большое снижение частоты кадров приведет к тому, что изменения пользовательского интерфейса будут выполняться слишком медленно и не решат проблемы, которые мы наблюдаем. - person Herms; 05.12.2008
comment
Дело в том, что профилировщик утверждает, что САМ событие занимает 32% процессорного времени (плюс то, что оно вызывает, занимает 84%). Это очень значительный промежуток времени для мероприятия. Что-то происходит, но я не могу сказать что. - person Herms; 05.12.2008

Эта ссылка объясняет каждую из [функций], описанных в профилировщике производительности:

http://livedocs.adobe.com/flex/gumbo/html/WS6f97d7caa66ef6eb1e63e3d11b6c4d0d21-7edf.html

person Mark Ingram    schedule 22.07.2009

Обновленная ссылка Liveocs:

http://help.adobe.com/en_US/flashbuilder/using/WS6f97d7caa66ef6eb1e63e3d11b6c4d0d21-7edf.html

person Brent Arndorfer    schedule 14.06.2010

Джастин, спасибо за ответ. Проблема не в выполнении enterFrame, а в том, что он пытается сделать слишком много на каждой итерации.

К вашему сведению: по совпадению, мы с оригинальным постером имеем дело с одним и тем же приложением. Мы решили удалить все ресурсы Degrafa в пользу ProgrammaticSkins. Я сообщу здесь о результатах, когда мы закончим.

person Community    schedule 04.12.2008