2008-12-12 22 views
34

Estoy trabajando en un juego de iPhone 2D con OpenGL ES y sigo llegando al límite de memoria de 24 MB: mi aplicación sigue fallando con el código de error 101. Intenté realmente encontrar dónde va la memoria , pero los números en Instrumentos son todavía mucho más grandes de lo que esperaría.Comprender el consumo de memoria en iPhone

Ejecuté la aplicación con los instrumentos Memory Monitor, Object Alloc, Leaks y OpenGL ES. Cuando la aplicación se carga, la memoria física libre baja de 37 MB a 23 MB, el Object Alloc se instala alrededor de 7 MB, las filtraciones muestran dos o tres filtraciones de unos pocos bytes, el tamaño del objeto Gart es de aproximadamente 5 MB y el monitor de memoria dice la aplicación ocupa alrededor de 14 MB de memoria real. Estoy perplejo como a dónde fue la memoria: cuando profundizo en las asignaciones de objetos, la mayor parte de la memoria está en las texturas, exactamente como era de esperar. Pero tanto mi propio contador de asignación de textura como el Tamaño de objeto de Gart coinciden en que las texturas deberían ocupar alrededor de 5 MB.

No tengo conocimiento de asignar nada más que merezca la pena mencionar, y el Object Alloc está de acuerdo. ¿A dónde va la memoria? (Me gustaría que alegres suministrar más detalles si esto no es suficiente.)


Actualización: Realmente traté de encontrar donde podría asignar tanta memoria, pero sin resultados. Lo que me vuelve loco es la diferencia entre las asignaciones de objetos (~ 7 MB) y el uso real de la memoria como se muestra en el monitor de la memoria (~ 14 MB). Incluso si hubiera grandes fugas o trozos grandes de memoria que me olvidé, el aún debería aparecer en las Asignaciones de objetos, ¿o no?

Ya he probado el usualsuspects, es decir. el UIImage con su almacenamiento en caché, pero eso no ayudó. ¿Hay alguna manera de rastrear el uso de la memoria "depurador-estilo", línea por línea, viendo el impacto de cada declaración en el uso de la memoria?


Lo que he encontrado hasta ahora:

  1. Realmente am usando esta cantidad de memoria. No es fácil medir el consumo real de memoria, pero después de un montón de conteos, creo que el consumo de memoria es realmente tan alto. Mi culpa.

  2. No encontré una manera fácil de medir la memoria utilizada. Los números del Monitor de memoria son precisos (estos son los números que realmente importan), pero el Monitor de memoria no puede decirle dónde va exactamente la memoria. La herramienta Object Alloc es casi inútil para rastrear el uso real de la memoria. Cuando creo una textura, el contador de memoria asignada se sube por un tiempo (leyendo la textura en la memoria), luego se cae (pasando los datos de textura a OpenGL, liberando). Esto está bien, pero no siempre ocurre, a veces el uso de la memoria se mantiene alto incluso después de que la textura se transfiere a OpenGL y se libera de la memoria "my". Esto significa que la cantidad total de memoria asignada como se muestra en la herramienta Object Alloc es menor que el consumo de memoria total real, pero mayor que el consumo real menos las texturas (real – textures < object alloc < real). Imagínate.

  3. He leído mal la Guía de programación. El límite de memoria de 24 MB se aplica a texturas y superficies, no a toda la aplicación. La línea roja real se encuentra un poco más lejos, pero no pude encontrar ningún número difícil. El consenso es que 25-30 MB es el techo.

  4. Cuando el sistema tiene poca memoria, comienza a enviar la advertencia de memoria.No tengo casi nada que liberar, pero otras aplicaciones liberan algo de memoria al sistema, especialmente a Safari (que parece almacenar en caché los sitios web). Cuando la memoria libre como se muestra en el Monitor de Memoria se pone a cero, el sistema comienza a matar.

tuve que morder la bala y reescribir algunas partes del código para ser más eficientes en la memoria, pero estoy probablemente dejar de empujarla. Si tuviera que diseñar otro juego, ciertamente pensaría en una búsqueda de recursos. Con el juego actual es bastante difícil, porque la cosa está en movimiento todo el tiempo y cargar las texturas se pone en el camino, incluso si se hace en otro hilo. Estaría muy interesado en cómo otras personas resuelven este problema.

Tenga en cuenta que estos son solo mis puntos de vista que no tienen por qué ser muy precisos. Si encuentro algo más que decir sobre este tema, actualizaré la pregunta. Mantendré la pregunta abierta en caso de que alguien que entienda el problema cuide responder, ya que todos estos son más soluciones provisionales que cualquier otra cosa.

Respuesta

11

Dudo mucho que este es un error de un instrumento.

En primer lugar, lea este blog post by Jeff Lamarche about openGL textures:

  • tiene un ejemplo sencillo de cómo cargar texturas sin fugas que causan
  • da comprensión de cómo los "pequeños" imágenes, obtener una vez que se cargan en OpenGL, utilizar realmente "mucho" de la memoria

Extracto:

texturas, incluso si están hechas de imágenes comprimidas, utilizar una gran cantidad de montón de memoria de la aplicación porque tienen que ser ampliado en la memoria que se utiliza . Cada píxel ocupa cuatro bytes, , olvidando liberar su textura los datos de imagen pueden realmente comer su memoria rápidamente.

En segundo lugar, es posible depurar la memoria de textura con instrumentos. Hay dos configuraciones de perfil: OpenGL ES Analyzer y OpenGL ES Driver. Deberá ejecutarlos en el dispositivo, ya que el simulador no utiliza OpenGL. Simplemente elija Producto-> Perfil de XCode y busque estos perfiles una vez que se inicie Instruments.


Armado con este conocimiento, esto es lo que yo haría:

  • Compruebe que no estás leaking memory - Obviamente, esto hará que este problema.
  • Asegúrese de que no accessing autoreleased memory - causa común de fallas.
  • Crea una aplicación de prueba por separado y juega con la carga de texturas individualmente (y en combinación) para descubrir qué textura (o combinación de las mismas) está causando el problema.

ACTUALIZACIÓN: Después de pensar en su pregunta, he estado leyendo Apple's OpenGL ES Programming Guide y tiene muy buena información. ¡Muy recomendable!

+0

El enlace al artículo está muerto, ¿alguna idea de dónde puedo encontrar esta información? – cheeesus

+0

Agregué información acerca de lo que el artículo hablaba. También eliminé el enlace muerto. – bentford

+0

Estoy mirando las configuraciones de OpenGL ES Analyzer y OpenGL ES Driver, y no puedo encontrar la cantidad de memoria de textura utilizada. ¿Cómo se obtiene la memoria de textura OpenGL utilizada para una aplicación iOS? –

0

Esto no lo ayuda específicamente, pero si encuentra que las herramientas de memoria no proporcionan todos los datos que necesita, presente un error en bugreport.apple.com. Adjunte una copia de su aplicación y una descripción de cómo las herramientas no alcanzan su análisis y Apple verá si pueden mejorar las herramientas. ¡Gracias!

2

Hrmm, que no es muchos detalles, pero si hay fugas no le muestra dónde están las fugas, hay dos opciones importantes:

[i] Las fugas echado una fuga [ii] La memoria no es en realidad se filtró

la fijación [i] es bastante difícil, pero como dijo Eric Albert, la presentación de un informe de error con Apple ayudará. [ii] significa que la memoria que estás utilizando todavía está accesible en algún lado, pero quizás te hayas olvidado de ella. ¿Hay listas en crecimiento, sin tirar entradas antiguas? ¿Hay algún búfer realloc() ed mucho?

+0

Cualquier código encapsulado dentro de las llaves de una llamada de despacho a GCD está protegido de dos cosas: informe de errores y, en ocasiones, recuento de asignaciones. Eso generalmente solo se aplica a CoreFoundation o cualquier otra cosa que no sea UIKit o no NSFoundation. –

3

Una forma es comenzar a comentar el código y verificar si el error persiste. Sí, es tedioso y elemental, pero podría ser útil si supieras dónde estaba el error.

los casos en que está fallando es por eso que está fallando, etc.

+0

Lamentablemente, esto no funciona, no puedo simplemente comentar una asignación y espero que la aplicación no se dé cuenta. – zoul

+0

En realidad, este no es un mal consejo. Si la aplicación consume más y más memoria, es posible comentar partes del código de asignación de memoria y reducir los posibles sospechosos a una sola clase o línea. – zoul

2

Para aquellos de ver esto a partir del año 2012:

La memoria muy cargado en la memoria física del dispositivo es la memoria residente en VM Rastreador de instrumentos.

El instrumento de asignación solo marca la memoria creada por malloc/[NSObject alloc] y algo de buffer de marco, por ejemplo, el mapa de bits descomprimido no se incluye en el instrumento de asignación pero siempre ocupa la mayor parte de la memoria.

Mire WWDC 2012 Session 242 iOS App Performance: Memory para obtener la información de Apple.

Cuestiones relacionadas