iOS
Perfil con instrumentos
Buscar..
Introducción
Xcode incluye una aplicación de ajuste de rendimiento llamada Instruments que puede usar para perfilar su aplicación utilizando todo tipo de métricas diferentes. Tienen herramientas para inspeccionar el uso de la CPU, el uso de la memoria, las fugas, la actividad de archivos / redes y el uso de la energía, solo por nombrar algunos. Es muy fácil comenzar a perfilar su aplicación desde Xcode, pero a veces no es tan fácil entender lo que ve cuando se perfila, lo que disuade a algunos desarrolladores de poder usar esta herramienta en todo su potencial.
Perfilador de tiempo
El primer instrumento que verás es el Time Profiler
. A intervalos medidos, los instrumentos detendrán la ejecución del programa y tomarán un seguimiento de la pila en cada subproceso en ejecución. Piense en ello como presionar el botón de pausa en el depurador de Xcode. Aquí hay una vista previa del Time Profiler:
Esta pantalla muestra el Call Tree
. El Call Tree
muestra la cantidad de tiempo empleado en la ejecución de varios métodos dentro de una aplicación. Cada fila es un método diferente que ha seguido la ruta de ejecución del programa. El tiempo empleado en cada método se puede determinar a partir del número de veces que se detiene el generador de perfiles en cada método. Por ejemplo, si 100 muestras se realizan a intervalos de 1 milisegundo y se encuentra que un método en particular está en la parte superior de la pila en 10 muestras, entonces puede deducir que se gastó aproximadamente el 10% del tiempo total de ejecución ( 10 milisegundos ) en ese metodo Es una aproximación bastante cruda, ¡pero funciona!
Desde Xcode's
barra de menú Xcode's
, seleccione Product\Profile
o press ⌘I
. Esto construirá la aplicación y lanzará Instruments. Serás recibido con una ventana de selección que se ve así:
Estas son todas las diferentes plantillas que vienen con los instrumentos.
Seleccione el instrumento Time Profiler
y haga clic en Elegir. Esto abrirá un nuevo documento de instrumentos. Haga clic en el botón rojo de grabación en la parte superior izquierda para comenzar a grabar e iniciar la aplicación. Es posible que se le solicite su contraseña para autorizar a Instruments a analizar otros procesos. No dude, es seguro proporcionarlos aquí. En la ventana de Instrumentos , puede ver el tiempo contando y una pequeña flecha moviéndose de izquierda a derecha sobre el gráfico en el centro de la pantalla. Esto indica que la aplicación se está ejecutando.
Ahora, empieza a usar la aplicación. Busque algunas imágenes y profundice en uno o más de los resultados de búsqueda. Probablemente haya notado que entrar en un resultado de búsqueda es tediosamente lento, y desplazarse por una lista de resultados de búsqueda también es increíblemente molesto: ¡es una aplicación terriblemente torpe!
Bueno, estás de suerte, ¡porque estás a punto de embarcarte en arreglarlo! Sin embargo, primero vas a ver rápidamente lo que estás viendo en Instruments . Primero, asegúrese de que el selector de vista en el lado derecho de la barra de herramientas tenga ambas opciones seleccionadas, así:
Eso asegurará que todos los paneles estén abiertos. Ahora estudie la captura de pantalla a continuación y la explicación de cada sección debajo de ella:
1. Estos son los controles de grabación . El botón rojo 'grabar' detendrá e iniciará la aplicación que actualmente se está perfilando cuando se hace clic (se alterna entre un icono de grabación y de detención). El botón de pausa hace exactamente lo que cabría esperar y detiene la ejecución actual de la aplicación.
2. Este es el temporizador de ejecución. El temporizador cuenta cuánto tiempo se ha estado ejecutando la aplicación que se está perfilando y cuántas veces se ha ejecutado. Si detiene y luego reinicia la aplicación usando los controles de grabación, se iniciará una nueva ejecución y la pantalla mostrará la Corrida 2 de 2.
3. Esto se llama una pista. En el caso de la plantilla de Time Profiler que seleccionó, solo hay un instrumento, así que solo hay una pista. Aprenderá más sobre los detalles del gráfico que se muestra aquí más adelante en el tutorial.
4. Este es el panel de detalle. Muestra la información principal sobre el instrumento en particular que está utilizando. En este caso, muestra los métodos que son "los más calientes", es decir, los que han consumido más tiempo de CPU. Si hace clic en la barra en la parte superior que dice Árbol de llamadas (la izquierda) y selecciona Lista de muestras, se le presenta una vista diferente de los datos. Esta vista muestra cada una de las muestras. Haga clic en algunas muestras y verá que la traza de la pila capturada aparece en el inspector de detalles extendidos.
5. Este es el panel de inspectores. Hay tres inspectores: Configuración de registro, Configuración de pantalla y Detalle extendido. En breve aprenderás más sobre algunas de estas opciones.
Perforación profunda
Realice una búsqueda de imágenes y profundice en los resultados. Personalmente, me gusta buscar "perro", pero elige lo que desees, ¡puedes ser una de esas personas gato!
Ahora, desplácese hacia arriba y hacia abajo en la lista unas cuantas veces para obtener una buena cantidad de datos en el Time Profiler
. Debes notar que los números en el centro de la pantalla cambian y el gráfico se completa; Esto le indica que se están utilizando ciclos de CPU .
¡Realmente no esperaría que una UI fuera tan torpe como esta, ya que ninguna table view
está lista para enviarse hasta que se desplace como la mantequilla! Para ayudar a identificar el problema, necesita establecer algunas opciones.
En el lado derecho, seleccione el inspector de configuración de pantalla (or press ⌘+2)
. En el inspector , en la sección Call Tree
, seleccione Separar por hilo , Invertir Call Tree
, Ocultar símbolos que faltan y Ocultar bibliotecas del sistema. Se verá así:
Esto es lo que hace cada opción con los datos que se muestran en la tabla de la izquierda:
Separar por hilo: cada hilo debe considerarse por separado. Esto le permite comprender qué subprocesos son responsables de la mayor cantidad de uso de la CPU .
Invertir árbol de llamadas: con esta opción, el stack trace
la stack trace
se considera de arriba a abajo. Esto suele ser lo que desea, ya que desea ver los métodos más profundos en los que la CPU está gastando su tiempo.
Ocultar símbolos que faltan: Si no se puede encontrar el archivo dSYM
para su aplicación o un system framework
, en lugar de ver los nombres de los métodos (símbolos) en la tabla, verá valores hexadecimales correspondientes a las direcciones dentro del binario. Si se selecciona esta opción, solo se muestran los símbolos totalmente resueltos y los valores hexadecimales sin resolver se ocultan. Esto ayuda a despejar los datos presentados.
Ocultar bibliotecas del sistema: cuando se selecciona esta opción, solo se muestran los símbolos de su propia aplicación. A menudo es útil seleccionar esta opción, ya que generalmente solo le importa dónde la CPU está gastando tiempo en su propio código. ¡No puede hacer mucho sobre la cantidad de CPU que utilizan las system libraries
del system libraries
!
Aplanar la recursión: esta opción trata las funciones recursivas (las que se llaman a sí mismas) como una entrada en cada stack trace
, en lugar de múltiples.
Funciones principales: habilitar esto hace que los Instruments
consideren el tiempo total empleado en una función como la suma del tiempo directamente dentro de esa función, así como el tiempo empleado en las funciones llamadas por esa función.
Entonces, si la función A llama a B, entonces el tiempo de A se informa como el tiempo empleado en A MÁS que el tiempo empleado en B. Esto puede ser realmente útil, ya que te permite elegir la cifra de tiempo más grande cada vez que desciendes en la pila de llamadas, poniendo a cero. en sus métodos más lentos.
Si está ejecutando una aplicación Objective-C
, también hay una opción de Mostrar solo Obj-C : si se selecciona esta opción, solo se muestran los métodos Objective-C
, en lugar de las funciones C
o C++
. No hay ninguno en su programa, pero si estaba buscando una aplicación OpenGL
, podría tener algún C++
, por ejemplo.
Aunque algunos valores pueden ser ligeramente diferentes, el orden de las entradas debe ser similar al de la siguiente tabla una vez que haya habilitado las opciones anteriores:
Bueno, eso ciertamente no se ve muy bien. La gran mayoría del tiempo se invierte en el método que aplica el filtro 'tonal' a las fotos en miniatura. Eso no debería ser una gran sorpresa para usted, ya que la carga y el desplazamiento de la tabla eran las partes más clásicas de la interfaz de usuario, y es cuando las celdas de la tabla se actualizan constantemente.
Para obtener más información sobre lo que sucede dentro de ese método, haga doble clic en su fila en la tabla. Al hacerlo aparecerá la siguiente vista:
Bueno, eso es interesante, ¿no? applyTonalFilter()
es un método agregado a UIImage
en una extensión, y casi el 100 % del tiempo invertido se dedica a crear la salida CGImage después de aplicar el filtro de imagen.
Realmente no hay mucho que se pueda hacer para acelerar esto: crear la imagen es un proceso bastante intensivo, y toma todo el tiempo necesario. Intentemos retroceder y ver desde dónde se llama a applyTonalFilter()
. Haga clic en Call Tree
en la ruta de navegación en la parte superior de la vista de código para volver a la pantalla anterior:
Ahora haga clic en la flecha pequeña a la izquierda de la fila de applyTonalFilter en la parte superior de la tabla. Esto desplegará el Árbol de llamadas para mostrar al llamante de applyTonalFilter. Puede que necesites desplegar la siguiente fila también; al perfilar Swift, a veces habrá filas duplicadas en el árbol de llamadas, con el prefijo @objc. Está interesado en la primera fila que tiene como prefijo el nombre de destino de su aplicación (InstrumentsTutorial):
En este caso, esta fila se refiere a cellForItemAtIndexPath
la vista de colección de cellForItemAtIndexPath
. Haga doble clic en la fila para ver el código asociado del proyecto.
Ahora puedes ver cual es el problema. El método para aplicar el filtro tonal tarda mucho tiempo en ejecutarse, y se llama directamente desde cellForItemAtIndexPath, que bloqueará el main thread
(y, por lo tanto, la IU completa) cada vez que solicite una imagen filtrada.
Asignaciones
Hay información detallada sobre todos los objetos que se están creando y la memoria que los respalda; También muestra que retain counts
de cada objeto. Para comenzar de nuevo con un nuevo instruments profile
, salga de la aplicación Instrumentos. Esta vez, genere y ejecute la aplicación, y abra Debug Navigator en el área de Navegadores. Luego haga clic en Memoria para mostrar gráficos de uso de memoria en la ventana principal:
Estos gráficos son útiles para obtener una idea rápida sobre el rendimiento de su aplicación. Pero vas a necesitar un poco más de poder. Haga clic Profile in Instruments
botón Profile in Instruments
y luego en Transferir para llevar esta sesión a Instrumentos . El instrumento de asignaciones se iniciará automáticamente.
Esta vez notarás dos pistas. Uno se llama Asignaciones, y el otro se llama Fugas. La pista de Asignaciones se discutirá en detalle más adelante; La pista de Fugas es generalmente más útil en Objective-C, y no se tratará en este tutorial. Entonces, ¿qué error vas a encontrar a continuación? Hay algo oculto en el proyecto que probablemente no sabes que está ahí. Es probable que haya oído hablar de las fugas de memoria. Pero lo que quizás no sepa es que en realidad hay dos tipos de fugas:
Las verdaderas fugas de memoria son aquellas en las que un objeto ya no está referenciado por nada sino que aún está asignado, lo que significa que la memoria nunca se puede reutilizar. Incluso con Swift y ARC
ayudando a administrar la memoria, el tipo más común de pérdida de memoria es un retain cycle or strong reference cycle
. Esto ocurre cuando dos objetos mantienen fuertes referencias entre sí, de modo que cada objeto evita que el otro sea desasignado. Esto significa que su memoria nunca se libera!
El crecimiento de la memoria sin límites es donde la memoria sigue siendo asignada y nunca se le da la oportunidad de ser desasignada . Si esto continúa para siempre, en algún momento se llenará system's memory
y tendrá un gran problema de memoria en sus manos. En iOS, esto significa que la aplicación será eliminada por el sistema.
Con el instrumento de Asignaciones ejecutándose en la aplicación, realice cinco búsquedas diferentes en la aplicación pero aún no profundice en los resultados. ¡Asegúrate de que las búsquedas tengan algunos resultados! Ahora deja que la aplicación se asiente un poco esperando unos segundos.
Debes haber notado que el gráfico en la pista de Asignaciones ha aumentado. Esto te dice que la memoria está siendo asignada. Es esta característica la que lo guiará para encontrar unbounded memory growth
.
Lo que vas a realizar es un generation analysis
. Para ello, presione el botón llamado Mark Generation. Encontrará el botón en la parte superior del inspector de configuración de pantalla:
Presiónelo y verá que aparece una bandera roja en la pista, así:
El propósito del generation analysis
de generation analysis
es realizar una acción varias veces y ver si la memoria está creciendo de manera unbounded fashion
. Profundice en una búsqueda, espere unos segundos a que se carguen las imágenes y luego regrese a la página principal. Entonces marca la generación otra vez. Haga esto repetidamente para diferentes búsquedas. Después de profundizar en algunas búsquedas, los instrumentos se verán así:
En este punto, deberías ser sospechoso. Observe cómo va el gráfico azul con cada búsqueda en la que profundiza . Bueno, eso ciertamente no es bueno. Pero espera, ¿qué pasa con las memory warnings?
Usted sabe acerca de esos, ¿verdad? Memory warnings
son la forma que tiene iOS de decirle a una aplicación que las cosas se están apretando en el departamento de memoria, y usted necesita borrar algo de memoria.
Es posible que este crecimiento no se deba únicamente a su aplicación; podría ser algo en las profundidades de UIKit
que se aferra a la memoria. Dé a los marcos del sistema y a su aplicación la oportunidad de borrar su memoria antes de señalar con el dedo a cualquiera de ellos.
Simule una memory warning
seleccionando Instrument\Simulate Memory Warning
en la barra de menú de Instrumentos, o Hardware\Simulate Memory Warning
en la barra de menú simulator's
. Notarás que el uso de la memoria disminuye un poco, o tal vez no. Ciertamente no vuelvo a donde debería estar. Así que todavía hay un crecimiento ilimitado de memoria en algún lugar.
La razón para marcar una generación después de cada iteración de profundizar en una búsqueda es que puede ver qué memoria se ha asignado entre cada generación. Echa un vistazo en el panel de detalles y verás un montón de generaciones.