Asignación de memoria del sistema utilizando el subsistema malloc
La memoria se asigna a las aplicaciones que utilizan el subsistema malloc .
El subsistema malloc es una API de gestión de memoria que consta de las subrutinas siguientes:
- malloc
- calloc
- reasignación
- free
- mallopt
- mallinfo
- alóca
- valloc
- posix_memalign
El subsistema malloc gestiona un objeto de memoria lógica denominado almacenamiento dinámico. El almacenamiento dinámico es una región de memoria que reside en el espacio de direcciones de la aplicación entre el último byte de datos asignado por el compilador y el final de la región de datos. El almacenamiento dinámico es el objeto de memoria desde el que se asigna memoria y a la que la API del subsistema malloc devuelve memoria.
- Asignación:
Realizado por las subrutinas malloc, calloc valloc, allocay posix_memalign .
- Desasignación:
Realizado por la subrutina free .
- Reasignación:
Realizado por la subrutina realloc .
Las subrutinas mallopt y mallinfo están soportadas para la compatibilidad con System V. La subrutina mallinfo se puede utilizar durante el desarrollo del programa para obtener información sobre el almacenamiento dinámico gestionado por la subrutina malloc . La subrutina mallopt se puede utilizar para descartar la memoria libre de tamaño de página alineada con páginas y para habilitar e inhabilitar el asignador predeterminado. De forma similar a la subrutina malloc , se proporciona la subrutina valloc para la compatibilidad con Berkeley Compatibility Library.
Para obtener información adicional, consulte las secciones siguientes:
Trabajar con el almacenamiento dinámico de proceso
_edata es un símbolo cuya dirección es el primer byte después del último byte de datos de programa inicializados. El símbolo _edata hace referencia al inicio del almacenamiento dinámico de proceso, que se amplía mediante el subsistema malloc cuando se asigna el primer bloque de datos. El subsistema malloc aumenta el almacenamiento dinámico de proceso aumentando el valor brk de proceso, que indica el final del almacenamiento dinámico de proceso. Esto se realiza llamando a la subrutina sbrk . El subsistema malloc expande el almacenamiento dinámico de proceso según las necesidades de la aplicación.
El almacenamiento dinámico de proceso se divide en bloques de memoria asignados y liberados . La agrupación libre consta de la memoria disponible para la asignación posterior. Una asignación se completa eliminando primero un bloque de memoria de la agrupación libre y luego devolviendo a la función de llamada un puntero a este bloque. Se completa una reasignación asignando un bloque de memoria del nuevo tamaño, moviendo los datos del bloque original al nuevo bloque y liberando el bloque original. Los bloques de memoria asignados constan de las partes del almacenamiento dinámico de proceso que utiliza la aplicación. Puesto que los bloques de memoria no se eliminan físicamente del almacenamiento dinámico (cambian el estado de libre a asignado), el tamaño del almacenamiento dinámico de proceso no disminuye cuando la aplicación libera memoria.
Espacio de direcciones de proceso en aplicaciones de 32 bits
Un programa de aplicación de 32 bits que se ejecuta en el sistema tiene un espacio de direcciones dividido en los segmentos siguientes:
| Segmento | Descripción |
|---|---|
| 0x00000000por:0x0fffffff | Contiene el kernel. |
| 0x10000000por:0x1fffffff | Contiene el texto del programa de aplicación. |
| 0x20000000por:0x2fffffff | Contiene los datos del programa de aplicación, el almacenamiento dinámico de proceso y la pila de aplicación. |
| 0x30000000por:0xcfffffff | Disponible para que lo utilicen la memoria compartida o los servicios mmap . |
| 0xd0000000por:0xdfffffff | Contiene texto de biblioteca compartida. |
| 0xe0000000por:0xefffffff | Disponible para que lo utilicen la memoria compartida o los servicios mmap . |
| 0xf0000000por:0xffffffff | Contiene los datos de la biblioteca compartida de la aplicación. |
Espacio de direcciones de proceso en aplicaciones de 64 bits
Un programa de aplicación de 64 bits que se ejecuta en el sistema tiene un espacio de direcciones dividido en los segmentos siguientes:
| Segmento | Descripción |
|---|---|
| 0x0000 0000 0000 0000por:0x0000 0000 0fff ffff | Contiene el kernel. |
| 0x0000 0000 f000 0000por:0x0000 0000 ffff ffff | Reservado. |
| 0x0000 0001 0000 0000por:0x07ff ffff ffff ffff | Contiene el texto del programa de aplicación, los datos del programa de aplicación, el almacenamiento dinámico de proceso y la memoria compartida o los servicios mmap . |
| 0x0800 0000 0000 0000por:0x08ff ffff ffff ffff | Objetos cargados de forma privada. |
| 0x0900 0000 0000 0000por:0x09ff ffff ffff ffff | Texto y datos de biblioteca compartida. |
| 0x0f00 0000 0000 0000por:0x0fff ffff ffff ffff | Pila de aplicación. |
PSALLOC=early cambia la técnica de asignación de espacio de paginación a un algoritmo de asignación temprana. En la asignación temprana, el espacio de paginación se asigna una vez que se solicita la memoria. Para obtener más información, consulte Espacio de paginación y memoria virtual en Sistema operativo y gestión de dispositivos.Descripción de la política de asignación del sistema
La política de asignación hace referencia al conjunto de estructuras de datos y algoritmos empleados para representar el almacenamiento dinámico y para implementar la asignación, la desasignación y la reasignación. El subsistema malloc soporta varias políticas de asignación diferentes, incluyendo la política de asignación predeterminada, la política de asignación de Watson, la política de asignación malloc 3.1 y la política de asignación definida por el usuario. La API para acceder al subsistema malloc es idéntica para todas las políticas de asignación; sólo la implementación subyacente es diferente.
- MALLOCTYPE especifica la política de asignación.
- MALLOCOPTIONS especifica opciones normales para la política de asignación elegida.
- MALLOCDEBUG especifica opciones de depuración para la política de asignación elegida.
- MALLOCALIGN especifica la alineación malloc predeterminada externa a un programa.
La política de asignación predeterminada es generalmente más eficiente y es la opción preferida para la mayoría de las aplicaciones. Las otras políticas de asignación tienen algunas características de comportamiento exclusivas que pueden ser beneficiosas en circunstancias específicas, tal como se describe en Comparación de las distintas políticas de asignación.
Algunas opciones de las distintas políticas de asignación son compatibles entre sí y pueden utilizarse conjuntamente. Cuando utilice opciones en tándem, utilice una coma (,) para separar las opciones especificadas por las variables de entorno MALLOCOPTIONS y MALLOCDEBUG .
MALLOCALIGN=16; export MALLOCALIGNLa variable de entorno MALLOCALIGN se puede establecer en cualquier potencia de 2 valores mayor o igual que el tamaño de un puntero en la modalidad de ejecución correspondiente (4 bytes para la modalidad de 32 bits, 8 bytes para la modalidad de 64 bits). Para programas habilitados para vectores de 32 bits, esta variable de entorno se puede establecer en 16, por lo que todos los malloc ()se alinearán adecuadamente para los tipos de datos de vector si es necesario. Tenga en cuenta que los programas vectoriales de 64 bits ya recibirán asignaciones alineadas de 16 bytes.Además, internamente en un programa, el programa puede utilizar la rutina mallopt (M_MALIGN, 16) para cambiar el valor predeterminado malloc () para proporcionar asignaciones alineadas de 16 bytes. La rutina mallopt (M_MALIGN) permite que un programa controle la alineación malloc predeterminada dinámicamente en tiempo de ejecución.
Descripción de la política de asignación predeterminada
La política de asignación predeterminada mantiene el espacio libre en el almacenamiento dinámico como nodos en un árbol de búsqueda binario cartesiano en el que los nodos se ordenan de izquierda a derecha por dirección (aumentando la dirección a la derecha) y de arriba a abajo por longitud (de modo que ningún hijo es mayor que su padre). Esta estructura de datos no impone ninguna limitación en el número de tamaños de bloque soportados por el árbol, lo que permite una amplia gama de tamaños de bloque potenciales. Las técnicas de reorganización de árbol optimizan los tiempos de acceso para la ubicación, inserción y supresión de nodos y también protegen contra la fragmentación.
La política de asignación predeterminada proporciona soporte para las siguientes prestaciones opcionales:
Asignación
Se necesita una pequeña cantidad de sobrecarga para dar servicio a una solicitud de asignación. Esto se debe a la necesidad de un prefijo de metadatos y a la necesidad de una alineación adecuada de cada bloque de memoria. El tamaño del prefijo de metadatos para todas las asignaciones es de 8 y 16 bytes para programas de 32 y 64 bits respectivamente. Cada bloque debe estar alineado en un límite de 16 o 32 bytes, por lo que la cantidad total de memoria necesaria para una asignación de tamaño n es:
size = roundup(n + prefix_size, alignment requirement)
Por ejemplo, una asignación de tamaño 37 en un proceso de 32 bits requeriría roundup(37 + 8, 16), que es igual a 48 bytes.
El nodo del árbol con la dirección más baja que es mayor o igual que el tamaño necesario se elimina del árbol. Si el bloque encontrado es mayor que el tamaño necesario, el bloque se divide en dos bloques: uno del tamaño necesario y el segundo un resto. El segundo bloque, denominado runt, se devuelve al árbol libre para su futura asignación. El primer bloque se devuelve al interlocutor.
Si no se encuentra un bloque de tamaño suficiente en el árbol libre, el almacenamiento dinámico se expande, se añade al árbol libre un bloque del tamaño de la extensión adquirida y la asignación continúa tal como se ha descrito anteriormente.
Desasignación
Los bloques de memoria desasignados con la subrutina free se devuelven al árbol, en la raíz. Cada nodo a lo largo de la vía de acceso al punto de inserción para el nuevo nodo se examina para ver si se une al nodo que se está insertando. Si lo hace, los dos nodos se fusionan y el nodo recién fusionado se reubica en el árbol. Si no se encuentra ningún bloque contiguo, el nodo simplemente se inserta en el lugar adecuado del árbol. La fusión de bloques adyacentes puede reducir significativamente la fragmentación del almacenamiento dinámico.
Reasignación
Si el tamaño del bloque reasignado será mayor que el bloque original, el bloque original se devuelve al árbol libre con la subrutina free para que pueda producirse cualquier posible coalescencia. A continuación, se asigna un nuevo bloque del tamaño solicitado, los datos se mueven del bloque original al nuevo bloque y el nuevo bloque se devuelve al interlocutor.
Si el tamaño del bloque reasignado es menor que el bloque original, el bloque se divide y el más pequeño se devuelve al árbol libre.
Limitaciones
Visión general de la política de asignación de Watson
La política de asignación de Watson mantiene el espacio libre en el almacenamiento dinámico como nodos en dos árboles rojo-negro separados: uno ordenado por dirección y el otro por tamaño. Los árboles rojo-negros proporcionan operaciones de árbol más sencillas y eficientes que los árboles cartesianos del asignador predeterminado, por lo que la política de asignación de Watson suele ser más rápida que la predeterminada.
Asignación
La política de asignación de Watson tiene los mismos requisitos de sobrecarga que la política de asignación predeterminada.
Se busca en el árbol de tamaño el bloque más pequeño posible que sea mayor o igual que el tamaño necesario. A continuación, este bloque se elimina del árbol de tamaño. Si el bloque encontrado es mayor que el tamaño necesario, el bloque se divide en dos bloques: un bloque del tamaño restante y el segundo del tamaño requerido. El primer bloque, denominado runt, se devuelve al árbol de tamaño para su futura asignación. El segundo bloque se devuelve al interlocutor. Si el bloque encontrado en el árbol de tamaño era exactamente el tamaño necesario, el bloque se elimina del tamaño y del árbol de direcciones y, a continuación, se devuelve al llamante.
Si no se encuentra un bloque de tamaño suficiente en el árbol libre, el almacenamiento dinámico de proceso se expande, se añade un bloque del tamaño de esta expansión a los árboles de tamaño y dirección, y la asignación continúa como se ha descrito anteriormente.
Desasignación
Los bloques de memoria desasignados con la subrutina free se devuelven al árbol de direcciones en la raíz. Cada nodo a lo largo de la vía de acceso al punto de inserción para el nuevo nodo se examina para ver si se une al nodo que se está insertando. Si lo hace, los dos nodos se fusionan y el nodo recién fusionado se reubica en el árbol de tamaño. Si no se encuentra ningún bloque contiguo, el nodo simplemente se inserta en el lugar adecuado en el árbol de direcciones y tamaño.
Después de la inserción, se debe comprobar el equilibrio correcto en ambos árboles rojo-negro.
Reasignación
Si el tamaño del bloque reasignado será mayor que el bloque original, el bloque original se devuelve a los árboles libres con la subrutina free para que se pueda producir cualquier posible coalescencia. A continuación, se asigna un nuevo bloque del tamaño solicitado, los datos se mueven del bloque original al nuevo bloque y el nuevo bloque se devuelve al interlocutor.
Si el tamaño del bloque reasignado es menor que el bloque original, el bloque se divide y el resto se devuelve al árbol libre.
Limitaciones
Política de asignación de malloc 3.1
La política de asignación de malloc 3.1 se puede seleccionar estableciendo MALLOCTYPE=3.1 antes del inicio del proceso. A partir de entonces, todos los programas de 32 bits ejecutados por el shell utilizarán la política de asignación malloc 3.1 (los programas de 64 bits seguirán utilizando la política de asignación predeterminada).
size = 2 i + 4donde i identifica el grupo. Esto significa que los bloques de la lista anclados por el grupo cero tienen una longitud de 20 + 4 = 16 bytes. Por lo tanto, dado que un prefijo tiene un tamaño de 8 bytes, estos bloques pueden satisfacer solicitudes de bloques de entre 0 y 8 bytes de longitud. La tabla siguiente ilustra cómo se distribuyen los tamaños solicitados entre los grupos.| Grupo | Tamaño de bloque | Tamaños correlacionados | Páginas utilizadas |
|---|---|---|---|
| 0 | 16 | 0 ... 8 | |
| 1 | 32 | 9 ... 24 | |
| 2 | 64 | 25 ... 56 | |
| 3 | 128 | 57 ... 120 | |
| 4 | 256 | 121 ... 248 | |
| 5 | 512 | 249 ... 504 | |
| 6 | 1K | 505 ... 1K-8 | |
| 7 | 2K | 1K-7 ... 2K-8 | |
| 8 | 4K | 2K-7 ... 4K-8 | 2 |
| 9 | 8K | 4K-7 ... 8K-8 | 3 |
| 10 | 16K | 8K-7 ... 16K-8 | 5 |
| 5 | 32K | 16K-7 ... 32K-8 | 9 |
| 6 | 64K | 32K-7 ... 64K-8 | 17 |
| 13 | 128K | 64K-7 ... 128K-8 | 33 |
| 14 | 256K | 128K-7 ... 256K-8 | 65 |
| 15 | 512K | 256K-7 ... 512K-8 | 129 |
| 16 | 1M | 256K-7 ... 1M-8 | 257 |
| 17 | 2M | 1M-7 ... 2M-8 | 513 |
| 18 | 4M | 2M-7 ... 4M-8 | 1K + 1 |
| 19 | 8M | 4M-7 ... 8M-8 | 2K + 1 |
| 20 | 16M | 8M-7 ... 16M-8 | 4K + 1 |
| 21 | 32M | 16M-7 ... 32M-8 | 8K + 1 |
| 22 | 64M | 32M-7 ... 64M-8 | 16K + 1 |
| 23 | 128M | 64M-7 ... 128M-8 | 32K + 1 |
| 24 | 256M | 128M-7 ... 256M-8 | 64K + 1 |
| 25 | 512M | 256M-7 ... 512M-8 | 128K + 1 |
| 26 | 1024M | 512M-7 ... 1024M-8 | 256K + 1 |
| 27 | 2048M | 1024M-7 ... 2048M-8 | 512K + 1 |
Asignación
Un bloque se asigna desde la agrupación libre convirtiendo primero los bytes solicitados en un índice en la matriz de grupos, utilizando la ecuación siguiente:
needed = requested + 8
If needed <= 16,
then
bucket = 0
If needed > 16,
then
bucket = (log(needed)/log(2) rounded down to the nearest integer) - 3
El tamaño de cada bloque de la lista anclada por el grupo esblock size = 2 bucket + 4. Si la lista del grupo es nula, la memoria se asigna utilizando la subrutina Sbrk para añadir bloques a la lista. Si el tamaño de bloque es menor que una página, se asigna una página utilizando la subrutina sbrk y el número de bloques a los que se ha llegado dividiendo el tamaño de bloque en el tamaño de página se añade a la lista. Si el tamaño de bloque es igual o mayor que una página, la memoria necesaria se asigna utilizando la subrutina sbrk y se añade un único bloque a la lista de libres para el grupo. Si la lista libre no está vacía, el bloque situado al principio de la lista se devuelve al llamante. El siguiente bloque de la lista se convierte entonces en la nueva cabeza.
Desasignación
Cuando se devuelve un bloque de memoria a la agrupación libre, el índice de grupo se calcula como con asignación. A continuación, el bloque que se va a liberar se añade a la cabecera de la lista de libres para el grupo.
Reasignación
Cuando se reasigna un bloque de memoria, el tamaño necesario se compara con el tamaño existente del bloque. Debido a la varianza amplia en tamaños manejados por un solo grupo, el nuevo tamaño de bloque a menudo se correlaciona con el mismo grupo que el tamaño de bloque original. En estos casos, la longitud del prefijo se actualiza para reflejar el nuevo tamaño y se devuelve el mismo bloque. Si el tamaño necesario es mayor que el bloque existente, el bloque se libera, se asigna un bloque nuevo del nuevo grupo y los datos se mueven del bloque antiguo al bloque nuevo.
Limitaciones
El establecimiento de MALLOCTYPE=3.1 solo habilitará la política malloc 3.1 para programas de 32 bits. Para que los programas de 64 bits utilicen la política malloc 3.1 , la variable de entorno MALLOCTYPE debe establecerse explícitamente en MALLOCTYPE=3.1_64BIT. Esta política de asignación es menos eficaz que la predeterminada y no se recomienda su uso en la mayoría de los casos.
La política de asignación malloc 3.1 da soporte a las opciones siguientes:
Descripción de la política de asignación de agrupaciones
La agrupación Malloc es un front-end de alto rendimiento para las funciones de libc malloc, calloc, free, posix_memalign y realloc para gestionar objetos de almacenamiento menores de 513 bytes. Las ventajas de rendimiento se derivan de longitudes de vía de acceso mucho más cortas y de una mejor utilización de la memoria caché de datos. Para aplicaciones multihebra, existe la ventaja adicional de que las anclas de agrupación local de hebras se utilizan para evitar operaciones atómicas. Este front-end se puede utilizar junto con cualquiera de los esquemas de gestión de almacenamiento que se proporcionan actualmente en libc (yorktowny watson).
export MALLOCOPTIONS=pool<:max_size> Cuando se especifica esta opción, se crea una colección de agrupaciones durante la inicialización de malloc donde cada agrupación es una lista enlazada de objetos de tamaño fijo. La agrupación más pequeña puede contener objetos de tamaño de puntero (por ejemplo, 8 bytes para aplicaciones de 32 bits o 16 bytes para aplicaciones de 64 bits). Cada agrupación sucesiva puede acomodar objetos cuyo tamaño sea mayor que la agrupación anterior. Esto significa que hay 128 agrupaciones para aplicaciones de 32 bits y 64 agrupaciones para aplicaciones de 64 bits. La colección de agrupaciones se representa como una matriz de punteros que "anclan" las listas enlazadas.
La agrupación Malloc utiliza su propia memoria, el almacenamiento dinámico de la agrupación, que no se comparte con mallocestándar. Cuando se especifica, la opción max_size se redondea al siguiente valor superior de 2 MB y se utiliza para controlar el tamaño del almacenamiento dinámico de la agrupación. La opción max_size se puede especificar como un número decimal o un número hexadecimal precedido por 0x o 0X (por ejemplo, export MALLOCOPTIONS=pool:0x1700000 establecerá max_size en 24 MB después del redondeo.
Para aplicaciones de 32 bits, el tamaño del almacenamiento dinámico de agrupación se inicia en 2 MB. Si se necesita más almacenamiento y el almacenamiento dinámico total de la agrupación es menor que tamaño_máx, se adquieren 2 MB adicionales. Cada área de 2 MBb estará en un límite de 2 MB, pero no es necesario que sea contigua a ninguna de las otras áreas de 2 MB. Para aplicaciones de 64 bits, se asigna un único almacenamiento dinámico de agrupación contigua de max_size durante la inicialización de malloc y nunca se amplía. Si no se especifica max_size , el valor predeterminado es 512 MB para aplicaciones de 32 bits y 32 MB para aplicaciones de 64 bits. Para las modalidades de 32 y 64 bits, tamaño_máximo se establecerá en 512 MB si se especifica un tamaño mayor. Para la modalidad de 32 bits, max_size se establece en 512MB, y para la modalidad de 64 bits, max_size se establece en 3.7 GB si se especifica un tamaño mayor.
Utilización de almacenamiento
Todas las anclas de agrupación se establecen inicialmente en NULL o están vacías. Cuando la agrupación malloc da servicio a una solicitud y la agrupación correspondiente está vacía, se llama a una rutina que asigna almacenamiento del almacenamiento dinámico de la agrupación en fragmentos de 1024 bytes contiguos en límites de 1024 bytes. Se "crean" varios objetos del tamaño solicitado. La dirección del primero se devuelve para satisfacer la solicitud, mientras que los objetos restantes se enlazan entre sí y se colocan en el ancla de la agrupación. Para cada fragmento de 1024 bytes, hay una entrada de 2 bytes en una tabla auxiliar que utiliza free para determinar el tamaño de un objeto devuelto.
Cuando una agrupación malloc libera un objeto, simplemente se "envía" al ancla de agrupación adecuada. No se realiza ningún intento de fusionar bloques para crear objetos de mayor tamaño.
Debido a este comportamiento, la agrupación malloc puede utilizar más almacenamiento que otras formas de malloc.
Alineación
La alineación predeterminada para las subrutinas malloc (), calloc ()y realloc () debe especificarse estableciendo la variable de entorno MALLOCALIGN de forma adecuada. La subrutina posix_memalign () continúa funcionando incluso si la variable de entorno MALLOCALIGN no está establecida. Si MALLOCALIGN es mayor que 512, no se utiliza la agrupación malloc .
Eficiencia de memoria caché
Los objetos de memoria asignados con agrupación malloc no tienen prefijos ni sufijos. Por lo tanto, las líneas de memoria caché de datos están más densamente empaquetadas con los datos utilizables de la aplicación. Como todos los objetos de memoria que tienen una potencia de 2 en tamaño están alineados en un límite igual a ese tamaño, cada objeto está contenido dentro del número mínimo de líneas de memoria caché. Las subrutinas malloc y free no exploran árboles ni listas enlazadas y, por lo tanto, no "contaminan" la memoria caché.
Soporte multihebra
Las agrupaciones Malloc pueden mejorar el rendimiento de forma significativa en un escenario multihebra porque reduce la contención de bloqueo y la necesidad de operaciones atómicas.
Soporte de equilibrio de carga
En algunos escenarios multihebra, la agrupación libre de una hebra puede crecer muy grande debido a la liberación repetitiva de memoria asignada dinámicamente. Sin embargo, es posible que otras hebras no puedan utilizar esta memoria.
El soporte de equilibrio de carga hace que una hebra libere la mitad de la memoria de cada agrupación a una agrupación global después de que la agrupación alcance un valor de umbral para que otras hebras puedan utilizarla. Puede ajustar los valores de umbral en los que se reajustará la agrupación de hebras.
Para activar el soporte de equilibrio de carga, se deben exportar las opciones siguientes:
export MALLOCOPTIONS=pool:0x80000000,pool_balanced export MALLOCFREEPOOL=min_size<-max_size>:threshold_value<,min_size<-max_size>:
threshold_value, ... >,default:thresholdEl ejemplo siguiente establece el valor de umbral para las agrupaciones que proporcionan una memoria de 0 -16 bytes y 256 fragmentos, y el valor de umbral de la agrupación que sirve fragmentos de 32 bytes a fragmentos de 512 bytes. Para el resto de las agrupaciones, los fragmentos de 128 bytes es el valor de umbral.export MALLOCFREEPOOL=0-16:256,32:512,default:128Soporte de depuración
No hay ninguna versión de depuración de este front-end de alto rendimiento. Si se establece la variable de entorno MALLOCDEBUG , la opción de agrupación se ignora. Se espera que las aplicaciones se depurarán utilizando malloc "normal" antes de activar la agrupación.
Descripción de la política de asignación definida por el usuario
El subsistema malloc proporciona un mecanismo a través del cual los usuarios pueden desarrollar sus propios algoritmos para gestionar el almacenamiento dinámico del sistema y asignar memoria.
Descripción de la opción no_overwrite
Una opción adicional disponible para todas las políticas de asignación es no_overwrite. Para reducir la sobrecarga del código glink dentro del subsistema malloc, el descriptor de función para las API del subsistema malloc se sobrescribe con el descriptor de función para la implementación subyacente real. Puesto que algunos programas, como los depuradores de terceros, pueden no funcionar cuando los punteros de función se modifican de esta forma, se puede utilizar la opción no_overwrite para inhabilitar esta optimización.
Para inhabilitar esta optimización, establezca MALLOCOPTIONS=no_overwrite antes del inicio del proceso.
Comparación de las distintas políticas de asignación
Las diversas políticas de asignación de malloc elaboradas anteriormente proporcionan flexibilidad a los desarrolladores de aplicaciones cuando se utilizan por separado o se combinan de formas soportadas. Es responsabilidad del desarrollador reconocer las necesidades exclusivas de una aplicación y ajustar los diversos parámetros de política de asignación de forma beneficiosa.
Comparación de las políticas de asignación predeterminadas y malloc 3.1
Puesto que la política de asignación malloc 3.1 redondea el tamaño de cada solicitud de asignación a la siguiente potencia de 2, puede producir una fragmentación de memoria virtual y real considerable y una localidad pobre de referencia. La política de asignación predeterminada es generalmente una mejor opción porque asigna exactamente la cantidad de espacio solicitada y es más eficiente en la reclamación de bloques de memoria utilizados anteriormente.
Desafortunadamente, algunos programas de aplicación pueden depender inadvertidamente de los efectos secundarios de la política de asignación malloc 3.1 para un rendimiento aceptable o incluso para un funcionamiento correcto. Por ejemplo, un programa que sobrepasa el final de una matriz puede funcionar correctamente cuando se utiliza el asignador malloc 3.1 sólo debido al espacio adicional proporcionado por el proceso de redondeo. Es probable que el mismo programa experimente un comportamiento errático o incluso falle cuando se utiliza con el asignador por omisión porque el asignador por omisión sólo asigna el número de bytes solicitado.
Como otro ejemplo, debido a la ineficiente reclamación de espacio del algoritmo de asignación malloc 3.1 , el programa de aplicación casi siempre recibe espacio que se ha establecido en ceros (cuando un proceso toca una página determinada en su segmento de trabajo por primera vez, esa página se establece en ceros). Las aplicaciones pueden depender de este efecto secundario para una ejecución correcta. De hecho, la reducción a cero del espacio asignado no es una función especificada de la subrutina malloc y daría como resultado una penalización de rendimiento innecesaria para los programas que se inicializan sólo según sea necesario y posiblemente no a ceros. Puesto que el asignador predeterminado es más agresivo sobre la reutilización de espacio, los programas que dependen de la recepción de almacenamiento con ceros de malloc probablemente fallarán cuando se utilice el asignador predeterminado.
De forma similar, si un programa reasigna continuamente una estructura a un tamaño ligeramente mayor, es posible que el asignador malloc 3.1 no tenga que mover la estructura con mucha frecuencia. En muchos casos, la subrutina realloc puede utilizar el espacio adicional proporcionado por el redondeo implícito en el algoritmo de asignación malloc 3.1 . El asignador predeterminado normalmente tendrá que mover la estructura a un área ligeramente más grande debido a la probabilidad de que la subrutina malloc llame a otra cosa justo por encima de ella. Esto puede presentar el aspecto de una degradación en el rendimiento de la subrutina realloc cuando se utiliza el asignador predeterminado en lugar del asignador malloc 3.1 . En realidad, es la afloración de un coste que está implícito en la estructura del programa de aplicación.
Depuración de la gestión incorrecta de la aplicación del almacenamiento dinámico del sistema
El subsistema malloc ofrece una colección de herramientas de depuración pensadas para ayudar al desarrollador de aplicaciones a depurar y corregir errores en la gestión de almacenamiento dinámico de un programa. Estas herramientas de depuración se controlan mediante la variable de entorno MALLOCDEBUG .
Sinopsis de la variable de entorno malloc y opciones
| multiheap (y subopciones) | grupos (y subopciones) | Memoria caché de hebras | no reclamar | no_sobrescritura | |
|---|---|---|---|---|---|
| Asignador predeterminado | Sí | Sí | Sí | Sí | Sí |
| 3.1 | No | No | Sí | Sí | Sí |
| Watson | No | No | No | No | No |
| Watson2 | No | No | No | No | No |
| usuario: | No | No | No | No | Sí |
| York Town < Asignador predeterminado > | 3.1 | Watson | Watson2 | usuario: | |
|---|---|---|---|---|---|
| catch_overflow (y subopciones) | Sí | No | Sí | Sí | No |
| asignaciones de informes | Sí | No | Sí | Sí | No |
| comprobación_postlibre | Sí | No | Sí | Sí | No |
| validate_ptrs | Sí | No | Sí | Sí | No |
| rastreo | Sí | No | Sí | Sí | No |
| anotaciones | Sí | No | Sí | Sí | No |
| verbose | No | No | No | No | No |
Descripción de la política de asignación de Watson2
El subsistema malloc Watson2 se adapta al comportamiento de la aplicación cuando cambia de una sola hebra a varias hebras y de varias hebras a una sola hebra. Utiliza un mecanismo específico de hebra que utiliza un número variable de estructuras de almacenamiento dinámico, que dependen del comportamiento del programa. Por lo tanto, no se necesitan opciones de configuración. El subsistema malloc Watson2 tiene O (logN) amortizado el coste por operación para muchas cargas de trabajo porque se puede ejecutar un gran número de operaciones en un momento constante sin sincronización.
Asignación
La asignación se maneja mediante una combinación de mecanismos. Estos mecanismos dependen de parámetros como, por ejemplo, el número de hebras activas, el tamaño de la solicitud y el historial de desasignación del proceso. El conjunto de mecanismos alcanza desde un almacenamiento en memoria caché específico de hebra y utiliza un número variable de almacenamientos dinámicos, que tiene afinidad de hebras con un árbol doble rojo-negro y fusión basada en página.
Desasignación
La desasignación depende de los mismos parámetros que el comportamiento de asignación. Normalmente, un bloque de devolución se captura en la memoria caché específica de hebra. En función de la afinidad de almacenamiento dinámico y la utilización de capacidad, la memoria puede devolverse a una de las varias estructuras de almacenamiento dinámico. A veces, el contenido de la estructura de almacenamiento dinámico múltiple se consolida en una estructura de almacenamiento dinámico común para mejorar la fusión y reducir la fragmentación del almacenamiento dinámico. Para mejorar la robustez frente a errores de aplicación, el asignador identifica la desasignación de punteros no válidos o bloques dañados, hasta cierto punto y filtra estas operaciones.
Reasignación
Los bloques grandes de memoria que son adecuados se reutilizan. Si el bloque actual no puede satisfacer la solicitud, se sustituye por una desasignación y asignación regulares.
Limitaciones
El subsistema malloc Watson2 se adapta a la aplicación y no requiere más opciones, pero el subsistema malloc Watson2 soporta las siguientes características de depuración controladas por la variable MALLOCDEBUG : validate_ptrs, report_allocations, y trace. Los informes relacionados con las asignaciones se pueden redirigir a un archivo utilizando la opción output:<filename> . Consulte Debug malloc tool para obtener información detallada sobre la variable MALLOCDEBUG .