flex profiling enterframeevent

Perfiles Flex: ¿qué está haciendo[enterFrameEvent]?



profiling (7)

Creo que tu problema está en otra parte. Esto sucede porque Flex se basa en Flash y Flash dispara ese evento tan a menudo como la velocidad de fotogramas (es decir, 20-30 veces por segundo).

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

EDITAR: No digo que tu solución sea bajar la velocidad de cuadros. Eso solo funcionaría si el evento que notaste fuera el problema. No estoy convencido de que eso sea realmente lo que está causando tus ralentizaciones. Puede ser que la llamada sea una función que causa el problema ... pero ese evento en sí no lo es. Se supone que debe disparar mucho.

Se me ha encomendado la tarea de encontrar (y posiblemente solucionar) algunos problemas graves de rendimiento con una aplicación Flex que nos fue entregada. La aplicación tomará de forma consistente entre el 50 y el 100% de la CPU en momentos en que simplemente está funcionando al ralentí y no debería estar haciendo nada.

Mi primer paso fue ejecutar el generador de perfiles que viene con FlexBuilder. Esperaba encontrar algún método que estuviera ocupando la mayor parte del tiempo, mostrándome dónde estaba el cuello de botella. Sin embargo, tengo algo inesperado.

Los mejores 4 métodos fueron:

  • [enterFrameEvent] - 84% acumulativo, 32% de tiempo propio
  • [cosechar]: 20% acumulativo y tiempo de autoaprendizaje
  • [tincan] - 8% acumulativo y tiempo del uno mismo
  • global.isNaN - 4% acumulado y tiempo de autoaprendizaje

Todos los otros métodos tenían menos del 1% tanto para el tiempo acumulativo como para el tiempo del auto.

Según lo que he encontrado en línea, los [métodos entre corchetes] son ​​los que el perfilador enumera cuando no tiene un método Flex real para mostrar. Vi a alguien afirmar que [tincan] es el procesamiento de solicitudes RTMP, y supongo que [cosechar] es el recolector de basura.

¿Alguien sabe lo que [enterFrameEvent] está haciendo realmente? Supongo que es esencialmente la función "principal" para el ciclo de eventos, por lo que se espera un tiempo acumulado alto. ¿Pero por qué el tiempo del yo es tan alto? ¿Qué está pasando realmente? No esperaba que las partes internas del jugador ocupen tanto tiempo, especialmente porque en realidad no sucede nada en la aplicación (y no hay actualizaciones de UI).

¿Hay alguna buena manera de buscar en lo que está sucediendo? que está sucediendo algo que no debería ser (parece que debe haber algún tipo de espera ocupada u otro bucle fuera de control), pero el generador de perfiles no me está dando ningún resultado que yo esperaba. Mi próximo paso será comenzar a agregar declaraciones de rastreo de depuración en varios lugares para intentar rastrear lo que realmente está sucediendo, pero creo que debe haber una forma mejor.


Justin, gracias por la respuesta. El problema no está en la ejecución de enterFrame, sino más bien tratando de hacer demasiado en cada iteración.

FYI: Casualmente, el póster original y yo estamos tratando con la misma aplicación. Hemos decidido eliminar todos los recursos de Degrafa a favor de ProgrammaticSkins. Informaré los hallazgos aquí cuando hayamos completado esto.


Algunas actualizaciones: no estamos haciendo nada en la aplicación más que escuchar eventos y usar enlaces ... es decir, sin ChangeWatchers, sin encuestas manuales ... solo esperando eventos. Estamos conectados a FMS todo el tiempo, por lo que hay algunos gastos generales para eso, pero es mínimo. Los enlaces no son muy eficientes en Flex, y hemos descubierto que no es bueno agregar la palabra clave de metadatos [Bindable] directamente a las clases (en gran volumen, con muchas clases). No estamos haciendo mucho de esto, pero es una manera de sacar un poco más rendimiento de su aplicación. Si usa [Bindable (event = "usersUpdated")], tendrá control sobre el enlace, y solo se activará cuando envíe el evento (nuevo Evento ("usersUpdated")) dentro de una función de la clase, es decir, su setter para ''usuarios''.

Cualquiera que haya usado System.gc () en Flex o AIR le dirá que la recolección de basura de Flex es una broma. Es una característica parcialmente implementada y nadie confía en ella. También hay trucos para esto ... llámalo dos veces, espera un cuadro, llámalo de nuevo. Puede limpiar tus objetos viejos, pero no cruces los dedos ... Flex hace lo que quiere.

Además, use objetos temporales para disminuir la cantidad de enlaces disparados. En lugar de...

myUser.location = new Location (); myUser.location.state = "CO"; myUser.location.city = "Denver";

hacer...

var tempLoc: Location = new Location (); tempLoc.state = "CO"; tempLoc.city = "Denver"; myUser.location = tempLoc;

El primero dispara 3 enlaces a cualquier cosa vinculada a la ubicación. *, Mientras que el último solo debe disparar 1 enlace (en realidad, generalmente es extra debido a la forma en que Flex lo maneja).

Los enlaces no matarán su aplicación hasta que tenga muchos de ellos en una aplicación visualmente rica ... el enlace y la representación parecen ser los trabajos más lentos de Flex.

Otra cosa interesante: crear una nueva aplicación Flex3 en Flex Builder y ejecutarla en el navegador. Nuestras pruebas mostraron que la CPU se mantiene entre el 8-10% en una MacBookPro (cuando la aplicación está inactiva y la ventana del navegador oculta). Nuestra aplicación ahora se ejecuta de manera constante en ~ 20% y mientras aumenta más para manejar los cambios de vista y similares, siempre vuelve a un nivel cercano al 20%. Nuestra preocupación inicial era que había una fuga de memoria o algo que se escapaba y que elevaría la CPU hasta un 40-50% (de nuevo, en el MBP ... todo en relación con esta máquina). Eliminamos todas las referencias a Degrafa y, aunque notamos un buen aumento en el rendimiento, no explicaba todo. Sin embargo, la aplicación Flex vacía fue esclarecedora: Flex en sí consume una CPU del 8-10% en todo momento, incluso cuando está inactivo.

Otro hallazgo más ... si usa Mate, tenga cuidado de cómo maneja las vistas de cambio. Es fácil tener activos disponibles y simplemente ocultarlos y deshabilitarlos cuando no se utilizan, mediante el uso de un inyector y un enlace en MXML, pero Flex no es muy inteligente cuando se trata de ocultar / deshabilitar cosas. Lo mejor es crear las vistas sobre la marcha y destruirlas cuando hayan terminado. Aunque la creación inicial puede llevar más tiempo y habrá una espera más larga entre las vistas, use algo de magia de visualización (una barra de progreso, un disco giratorio, etc.) para indicar que la vista se está alternando, espere a la creación completa en la vista y luego desvanecerse en él.

Además, aléjese de ViewStack para aplicaciones visualmente ricas. Administra tu propia pila.

Hasta ahora, este hilo repasó los problemas básicos de rendimiento comunes en cualquier idioma, pero Flex es un niño muy especial en muchos sentidos ("especial" no siempre se considera algo positivo). Hay innumerables trampas porque está construida sobre una plataforma muy visual, pero está diseñada para RIA, por lo que aunque Flash Player puede optimizar video, animaciones, etc., no optimizará una aplicación Flex. No espere que las aplicaciones Flex tengan el mismo rendimiento que las aplicaciones Flash. También hay una gran diferencia entre AVM (máquina virtual ActionScript) para AS2 y AS3.

Esto simplemente está arañando la superficie de los problemas de rendimiento y las ganancias potenciales en las aplicaciones de Flex. Este es un arte oscuro y es fácil ver por qué.

Código en, ninjas.


Hay un par de cosas que normalmente ocurren en un controlador enterframe dentro de un proyecto flexible. Algunas cosas para mirar

  1. Manual <mycomponent enterFrame = ""> respuestas de eventos o las agregadas manualmente a través de component.addEventListener (Event.ENTER_FRAME, myfunc)

  2. Las llamadas a callLater (), estas ocurren MUCHO en el marco y pueden ser un subproducto de saltar cualquier cantidad de agujeros de conejos, los desarrolladores tienden a usar estos para resolver problemas relacionados con el tiempo y a veces un código incorrecto puede hacer que estos continúen llamando a cada fotograma. Por ejemplo, hay ~ 120 apariciones de un calllater () en la última versión de flex sdk.

  3. por último, no puedo garantizar que el [enterframeEvent] maneja solo ingresar devoluciones de eventos de marco específico, y no eventos de temporizadores, mouse, etc., ya que enterframes ocurren durante el bucle de evento principal, es posible que vea el resultado acumulativo de todos los eventos activados del grupo de eventos principal. No estoy diciendo que esto ES lo que está pasando, pero tampoco puedo decir que NO ES lo que está sucediendo, no sé lo suficiente acerca de las partes internas para estar seguro.

/ edit también como se indicó anteriormente, el [enterFrameEvent] debería dispararse técnicamente al inicio de cada cuadro, pero no debería hacer nada a menos que los eventos se hayan adjuntado explícitamente para ejecutar el código de usuario.


Una actualización de esta publicación si alguien se encuentra con ella en el futuro ...

Unos pocos compañeros de trabajo en EffectiveUI tuvieron este problema exacto con su aplicación un par de meses más tarde, por lo que fue revisado. Se descubrió que al usar Flash para producir activos visuales, al usar STATEFUL SKINS y exportarlos a SWC con el kit de herramientas de activos de Flash / Flex, obtiene películas fugitivas (presumiblemente algo interno en la forma en que esto se implementa, por ejemplo, olvidando poner comandos stop () en marcos).

Aparentemente, no hay nada que pueda hacer al respecto excepto para entrar y eliminar todas las máscaras con estado. Una buena reseña se puede encontrar aquí:

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

Y una secuencia de comandos JSFL que puede usar para convertir máscaras con estado en máscaras sin estado:

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

¡Espero que esto ayude a alguien! Es un error muy desagradable y misterioso, pero puedes evitarlo.

Aclamaciones