Swift Managing Memory

Esta pregunta fue limpiada y la información importante se movió a la respuesta a continuación.


Tengo algunas preguntas sobre la gestión de la memory.

Estoy construyendo una aplicación de edición de fotos. Por lo tanto, mantener el uso de memory bajo es importante. Tampoco voy a publicar código porque no tengo una gran pérdida de memory cuando hago una cosa específica. Acabo de perder un par de KB / MB con todo lo que sucede. Y repasar decenas de miles de líneas de código para encontrar kilobytes no es divertido;)

mi aplicación utiliza datos básicos, muchos elementos encryptions, location y elementos básicos.

Mi primera vista es simplemente una vista de tabla que me cuesta alnetworkingedor de 5 MB de memory. Luego, tomas algunas fotos, aplicas algunos filters, esto se guarda en datos centrales y luego vuelves a esa primera vista.

¿Es posible realmente deshacerse de todo en la memory a exception de los datos necesarios para conducir esa primera vista? (eso muy ahorrador y asombroso 5mb)

¿O siempre quedará algo, incluso si configuras todo a cero?


Pregunta UIImageJPEGRepresentation : ¿hay alguna diferencia en el tamaño del file / carga cpu entre UIImageJPEGRepresentation y UIImagePNGRepresentation ? Sé que puedes establecer una calidad de compression con el método JPEG (¿más difícil en la cpu / gpu?).

Solo tratando de networkingucir la presión de la memory por todos los medios posibles.


Actualizar:

Me dijeron que la pregunta podría ser demasiado vaga.

Los problemas que tenía en algún momento u otro eran los siguientes:

  • En algunos puntos, el uso máximo de memory es demasiado alto.
  • Navegando hacia un segundo controller de vista y hacia atrás provoca una fuga
  • La edición de una image causa una pérdida de memory.
  • La aplicación de un filter a más de 4-5 imágenes provoca un locking debido a la falta de memory, ya no hubo pérdidas de memory en este momento. (verificado en instrumentos)

Todo esto fue probado en un iPhone 4s, no en el simulador.

Hubo un meme aquí para aligerar un poco el estado de ánimo de este sitio.

Esta pregunta ha sido abierta durante bastante time y ahora me siento lo suficientemente confiada para responderla.


Diferentes niveles de MM:

Memoria de hardware

En Swift con ARC, no tenemos forma de limpiar el ram de hardware actual. Solo podemos hacer que el sistema operativo lo haga por nosotros. Una parte está utilizando el código correcto ( optionals y weak ) y la otra parte está creando time para que el SO haga su trabajo.

Imagine que tenemos una function que se ejecuta en todos los hilos indefinidamente. Hace una cosa, carga una image, convierte a negro / blanco y guarda. Todas las imágenes máximas en un par de Mb y la function no crea pérdidas de memory de software. Debido a que las imágenes no tienen un tamaño configurado y pueden tener una compression diferente, no tienen la misma huella. Esta function siempre bloqueará su aplicación.

Esta pérdida de memory de "hardware" se debe a que la function siempre toma la siguiente ranura de memory disponible.

El sistema operativo no interviene para "limpiar realmente la memory" porque no hay time inactivo. Poner un retraso entre cada pase corrige por completo esto.


MM específico de idioma

Fundición

Algunas operaciones no tienen un impacto en la memory, otras lo hacen:

 let myInt : Int = 1 Float(myInt) // this creates a new instance 

Prueba en cambio:

 (myInt as Float) // this will not create a new instance. 

Tipos de reference vs Tipos de valores | Clases vs Structs

Ambos tienen sus ventajas y sus peligros.

Las estructuras son intensivas en memory porque son types de valor . Esto significa que copyn sus valores cuando se asignan a otra instancia, lo que duplica efectivamente el uso de la memory . No hay solución / solución para esto. Es lo que hace que Structs Structs.

Las classs no tienen este comportamiento porque son types de reference . No copyn cuando se les asigna. En cambio, crean otra reference al mismo object . ARC o conteo automático de references es lo que hace un seguimiento de estas references. Cada object tiene un contador de reference. Cada vez que lo asigna, sube uno. Cada vez que establece una reference a nil, la function adjunta finaliza o el object adjunto se desinmite, el contador se apaga.

Cuando el contador golpea 0, el object se desinicializa.

Existe una forma de evitar que una instancia desinicialice y, por lo tanto, cree una fuga. Esto se llama un fuerte ciclo de reference .

Buena explicación de Débil

 class MyClass { var otherClass : MyOtherClass? deinit { print("deinit") // never gets called } } class MyOtherClass { var myclass : MyClass? deinit { print("deinit") // never gets called } } var classA : MyClass? = MyClass() // sorry about the force unwrapping, don't do it like this classA!.otherClass = MyOtherClass() classA!.otherClass!.myclass = classA // this looks silly but in some form this happens a lot classA = nil // neither the MyClass nor the MyOtherClass deinitialised and we no longer have a reference we can acces. Immortalitiy reached they have. 

establecer una reference a weak

 class MyOtherClass { weak var myclass : MyClass? deinit { print("deinit") // gets called } } 

inout

Las funciones capturan los valores que se les pasan. Pero también es posible marcar esos valores como inout. Esto le permite cambiar un Struct pasado a una function sin copyr el Struct. Esto podría ahorrar memory, dependiendo de lo que pase y de lo que haga en la function.

También es una buena forma de tener múltiples valores de retorno sin usar tuplas.

 var myInt : Int = 0 // return with inout func inoutTest(inout number: Int) { number += 5 } inoutTest(&myInt) print(myInt) // prints 5 // basic function with return creates a new instance which takes up it's own memory space func addTest(number:Int) -> Int { return number + 5 } 

Progtwigción funcional

El estado es valor a través del time

La functional programming es la contrapartida de la progtwigción orientada a objects. La functional programming usa estado inmutable.

Más sobre esto aquí

La progtwigción orientada a objects usa objects que tienen estados cambiantes / mutantes. En lugar de crear un nuevo valor, los valores anteriores se actualizan.

La functional programming puede usar más memory.

ejemplo sobre FP


Opcionales

Las opciones le permiten establecer una cosa a cero. Esto networkingucirá el recuento de references de las classs o desinicializará las estructuras. Configurar las cosas a cero es la forma más fácil de limpiar la memory. Esto va de la mano con ARC. Una vez que haya establecido todas las references de una class a cero, desiniciará y liberará la memory.

Si no crea una instancia como opcional, los datos permanecerán en la memory hasta que finalice la function adjunta o la class adjunta deshabilite. Es posible que no sepas cuándo sucederá. Las opciones te dan control sobre lo que permanece vivo durante cuánto time.


API MM

Muchas "memory leaks" son causadas por Frameworks que tienen una function de "limpieza" que es posible que no haya llamado. Un buen ejemplo es UIGraphicsEndImageContext() El context permanecerá en memory hasta que se llame a esta function. No se limpia cuando termina la function que creó el context, o cuando la image involucrada se establece en nil.

Otro buen ejemplo es descartar ViewControllers. Podría tener sentido seguir a un VC y luego retroceder, pero segue crea un VC. Una segunda vuelta no destruye un VC. Llame a dismissViewControllerAnimated() para eliminarlo de la memory.

Lea las Referencias de class y verifique que no hay funciones de "limpieza".


Si necesita instrumentos para encontrar una fuga, consulte la otra respuesta sobre esta pregunta.

introduzca la descripción de la imagen aquí

click el nombre de su aplicación en la esquina superior derecha de Xcode.

introduzca la descripción de la imagen aquí

click 'editar esquema' en el menu que aparece.

introduzca la descripción de la imagen aquí

asegúrese de que 'RUN' esté seleccionado en el lado izquierdo, luego click la pestaña de diagnóstico cerca de la parte superior de la window.

bajo la cabecera de "gestión de la memory", compruebe que "habilite Guard Malloc"

es posible que también desee probar 'objects distribuidos' y 'malloc stack' bajo el encabezado 'logging'

Puede encontrar más información sobre guard malloc, bordes de guardia y garabatos aquí .

¡espero que esto ayude!