Archivos mapeados en memoria y escenarios de baja memoria
memory-management memory-mapped-files (6)
(Esta no es una respuesta, pero sería información útil.)
Del @ID_AA_Carmack tweet ,
@ID_AA_Carmack son archivos mapeados en la memoria de iOS que no se asignaron automáticamente en condiciones de poca memoria? (usando + [NSData dataWithContentsOfMappedFile]?)
ID_AA_Carmack respondió por esto,
@KhrobEdmonds Sí, ese es uno de los grandes beneficios de usar archivos mapeados en iOS. Yo uso mmap (), sin embargo.
No estoy seguro de que sea cierto o no ...
¿Cómo maneja la plataforma iOS archivos mapeados en memoria durante escenarios de baja memoria? En escenarios de baja memoria, quiero decir cuando el sistema operativo envía la notificación UIApplicationDidReceiveMemoryWarningNotification
a todos los observadores en la aplicación.
Nuestros archivos se mapean en la memoria usando +[NSData dataWithContentsOfMappedFile:]
, la documentación que indica:
Un archivo mapeado utiliza técnicas de memoria virtual para evitar copiar páginas del archivo en la memoria hasta que realmente se necesiten.
¿Esto significa que el sistema operativo también desasignará las páginas cuando ya no estén en uso? ¿Es posible marcar páginas como que ya no están en uso? Esta información es de solo lectura, si eso cambia el escenario. ¿Qué tal si tuviéramos que usar mmap()
directamente? ¿Sería esto preferible?
De mis experimentos NSData no responde a las advertencias de memoria. Probé creando un NSData mapeado en memoria y accediendo a partes del archivo para que se cargara en la memoria y finalmente enviara advertencias de memoria. No hubo disminución en el uso de memoria después de la advertencia de memoria. Nada en la documentación dice que una memoria hará que NSData reduzca el uso de la memoria real en situaciones de poca memoria, por lo que me hace creer que no responde a las advertencias de memoria. Por ejemplo, la documentación de NSCache dice que tratará de jugar bien con respecto al uso de la memoria, además me han dicho que responde a las advertencias de poca memoria que el sistema plantea.
También en mis simples pruebas con un iPod Touch (cuarta generación) pude mapear unos 600 megas de datos de archivos en la memoria virtual, uso +[NSData dataWithContentsOfMappedFile:]
. Luego comencé a acceder a las páginas a través de la propiedad bytes en la instancia de NSData. Mientras lo hacía, la memoria real comenzó a crecer, pero dejó de crecer a unos 30 megas de uso de memoria real. Entonces, la forma en que se implementa parece limitar la cantidad de memoria real que se utilizará.
En resumen, si desea reducir el uso de memoria de los objetos NSData, la mejor opción es asegurarse de que estén completamente liberados y de no confiar en nada que el sistema haga automágicamente en su nombre.
El método dataWithContentsOfMappedFile:
ahora está en desuso de iOS5.
Usa mmap, ya que evitarás estas situaciones.
Las técnicas de memoria virtual estándar para la memoria respaldada por archivos indican que el sistema operativo puede tirar las páginas cuando quiera, porque siempre las puede recuperar de nuevo más tarde. No he usado iOS, pero este ha sido el comportamiento de la memoria virtual en muchos otros sistemas operativos durante mucho tiempo.
La forma más sencilla de probarlo es mapear varios archivos grandes en la memoria, leerlos para garantizar que los coloca en la memoria y ver si puede forzar una situación de poca memoria. Si no puede, entonces el sistema operativo debe haber desasignado las páginas una vez que decidió que ya no estaban en uso.
Los archivos mapeados en memoria copian datos del disco en la memoria una página a la vez. Las páginas no utilizadas se pueden intercambiar libremente, al igual que cualquier otra memoria virtual, a menos que hayan sido conectadas a la memoria física usando mlock(2)
. El mapeo de memoria deja la determinación de qué copiar del disco a la memoria y cuándo al sistema operativo.
Dejar caer desde el nivel Foundation hasta el nivel BSD para usar mmap
es poco probable que haga mucha diferencia, más allá de hacer que el código que tiene que interactuar con otro código de Foundation sea algo más incómodo.
Si iOS es como cualquier otro Unix, y apuesto a que es en este sentido, las páginas en una región mmap () no se "intercambian"; simplemente se descartan (si están limpias) o se escriben en el archivo subyacente y luego se descartan (si están sucias). Este proceso se llama "desalojo" de la página.
Como su mapa de memoria es de solo lectura, las páginas siempre estarán limpias.
El kernel decidirá qué páginas desalojar cuando la memoria física se contrae.
Puedes darle al kernel sugerencias sobre qué páginas preferirías mantener / expulsar usando posix_madvise() . En particular, POSIX_MADV_DONTNEED
le dice al núcleo que puede desalojar las páginas libremente; o como dices, "marcar páginas como que ya no están en uso".
Debería ser bastante simple escribir algunos programas de prueba para ver si iOS respeta la sugerencia de "no necesito". Como se deriva de BSD, apuesto a que sí.