NSZone, gestión de zonas de memoria en OSX

Es posible que aunque desarrolleis aplicaciones en Objetive-C nunca os habeis visto en la necesidad de usar las zonas de memoria. Normalmente estos mecanismos se hacen de forma transparente y no tenemos que preocuparnos por ello. Pero si sois curiosos os llamará la atención como se asigna la memoria en las tripas del runtime del Objetive-C.

Al igual que mencionamos en el otro post de gestión de memoria en OSX, estos mecanismos, gracias al uso del garbage collector estan pasando a ser cosa del pasado. Ya que si usamos zonas con el recolector de basura activado, estas seran ignoradas. Sin embargo, y como dijimos en esa entrada, no siempre tenemos la posibilidad de desarrollar con el recolector de basura activado, como por ejemplo, si queremos que nuestra aplicación sea compatible con versiones anteriores de OSX o si desarrollamos para plataformas como iPhone o iPad donde esta funcionalidad aún no esta dispobible

Como se puede deducir del nombre del post, un NSZone representa una zona de memoria, que utilizaremos para alojar nuestros datos. Cuando creamos un programa, se crea una Zona por defecto, donde se alojaran todos nuestros objetos si no especificamos nada más, normalmente nos interesará crear y gestionar nuestra propia zona cuando vamos a hacer un uso especifico de dicha zona de memoria. Por ejemplo, si vamos a crear y liberar muchos objetos, quizas nos interese gestionar nuestra propia zona de memoria, en vez de realizar estas operaciones en la zona por defecto. Al alojar y desalojar memoria, siempre quedan zonas entre los diferentes objetos alojados que no son sencillas de reaprovechar, lo que aumenta la fragmentación, y teoricamente, empeora el rendimiento de nuestra aplicación. Además, y en teoria, los objetos de una zona estan próximos físicamente, con lo que si guardamos objetos relacionados entre si en la misma zona, el acceso desde uno a otro será mas rápido que si estan dispersos por la zona común.

Si teneis experiencia en C++, seguramente este concepto os recuerde a los “allocators” que se pueden utilizar cuando gestionamos ciertos objetos de STL.

Otro beneficio de la gestión manual de zonas es que si, colocamos N objetos en la memoria, será mucho mas rápido desalojarlos de nuestra propia zona que de la zona común del programa.

Hablando ya de ObjetiveC, la documentación es algo escasa, NSZone es una estructura de C, que guarda los datos referentes a la zona de memoria.

La función básica que nos sirve para crear una zona es:

NSZone * NSCreateZone (
NSUInteger startSize,
NSUInteger granularity,
BOOL canFree
);

A esta función le pasamos el tamaño inicial de la zona, el tamaño con el que crecerá o se encojerá en el parámetro granularity y le diremos si queremos que se libere memoria cuando se alojen nuevos objetos. Si le decimos que no, la reserva de memoria sera mas rápida ya que el algoritmo no tendrá que optimizar la zona cuando estemos reservando nueva memoria.

Para liberar una zona utilizaremos:

void NSRecycleZone (
NSZone *zone
);

Que no necesita mucha explicación, simplemente libera la zona que le pasamos como parámetro. La parte interesante, es que para prevenir problemas serios con objetos que esten en la zona cuando se Recicle, esta función, mueve los objetos vivos, de esta zona a la zona común.

Si queremos reservar memoria, explicitamente en una zona, podemos usar

void * NSZoneMalloc (
NSZone *zone,
NSUInteger size
);

Que nos reservara “size” bytes en la zona que le indicamos, devolviendonos un puntero a dicha porción de memoria.

Como podiamos esperar, la función que libera la memoria que acabamos de reservar es:

void NSZoneFree (
NSZone *zone,
void *ptr
);

Que es equivalente a lo que conocemos de “free” en C.

Todas estas funciones estan definidas en NSZone.h, dentro del Foundation framework

La gracia de las zonas, no es utilizar la memoria de esta forma “rudimentaria”, si no que, dicho concepto esta integrado completamente en el mecanismo de alocación de objetos en Objetive-C.

La clase padre de todas, NSObject, tiene dos metodos para alojar memoria, “alloc” y “allocWithZone:”.

De esta manera, cuando queremos crear un nuevo objeto, podemos usar esta variación de alloc, por ejemplo:

NSString * cadenaEnZona = [[NSString allocWithZone:mizona] init];

Que creará una cadena en la zona que le especificamos en lugar de en la zona común.

Debido a que este método esta en NSObject, cualquier objeto que creemos en nuestro proyecto, heredará este funcionamiento, y podremos instanciarlo en nuestra zona.

Además de este método allocWithZone, el otro método clave de NSObject para trabajar con Zones, es “copyWithZone:” que copiara el objeto especificado en otro, pero en la zona que le especificamos. Al igual que el método “copy”, el objeto a ser copiado, debe implementar la interfaz NSCopying, para asegurar que la copia del objeto se hace de forma adecuada.

2 respuestas a NSZone, gestión de zonas de memoria en OSX

  1. Juanjo dice:

    Muy interesante🙂

  2. robjperez dice:

    Gracias por el comentario

    Lo cierto es que muchos de estos detalles pasan desapercibidos, pero suele ser entretenido indagar un poquito mas en como funcionan las cosas🙂

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: