¿Cómo funciona malloc en un entorno multiproceso?
¿El típico malloc
(para la plataforma x86-64 y el sistema operativo Linux) bloquea ingenuamente un mutex al principio y lo libera cuando se hace, o bloquea un mutex de una manera más inteligente a un nivel más fino, de modo que la contención de bloqueo se reduce? Si realmente lo hace de la segunda manera, ¿cómo lo hace?
2 answers
glibc 2.15
opera múltiples arenas de asignación . Cada arena tiene su propia cerradura. Cuando un subproceso necesita asignar memoria, malloc()
selecciona una arena, la bloquea y asigna memoria de ella.
El mecanismo para elegir una arena es algo elaborado y está dirigido a reducir la contención de bloqueo:
/* arena_get() acquires an arena and locks the corresponding mutex.
First, try the one last locked successfully by this thread. (This
is the common case and handled with a macro for speed.) Then, loop
once over the circularly linked list of arenas. If no arena is
readily available, create a new one. In this latter case, `size'
is just a hint as to how much memory will be required immediately
in the new arena. */
Con esto en mente, malloc()
básicamente se ve así (editado para brevedad):
mstate ar_ptr;
void *victim;
arena_lookup(ar_ptr);
arena_lock(ar_ptr, bytes);
if(!ar_ptr)
return 0;
victim = _int_malloc(ar_ptr, bytes);
if(!victim) {
/* Maybe the failure is due to running out of mmapped areas. */
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
(void)mutex_lock(&ar_ptr->mutex);
victim = _int_malloc(ar_ptr, bytes);
(void)mutex_unlock(&ar_ptr->mutex);
} else {
/* ... or sbrk() has failed and there is still a chance to mmap() */
ar_ptr = arena_get2(ar_ptr->next ? ar_ptr : 0, bytes);
(void)mutex_unlock(&main_arena.mutex);
if(ar_ptr) {
victim = _int_malloc(ar_ptr, bytes);
(void)mutex_unlock(&ar_ptr->mutex);
}
}
} else
(void)mutex_unlock(&ar_ptr->mutex);
return victim;
Este asignador se llama ptmalloc
. Se basa en trabajos anteriores de Doug Lea, y es mantenido por Wolfram Gloger.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-22 17:17:15
Doug Lea malloc
bloqueo grueso usado (o ningún bloqueo, dependiendo de los ajustes de configuración), donde cada llamada a malloc
/realloc
/free
está protegido por un mutex global. Esto es seguro, pero puede ser ineficiente en entornos altamente multiproceso.
ptmalloc3
, que es la implementación predeterminada malloc
en la biblioteca C de GNU (libc) utilizada en la mayoría de los sistemas Linux en estos días, tiene una estrategia más precisa, como se describe en la respuesta de aix , que permite múltiples subprocesos para asignar simultáneamente la memoria de forma segura.
nedmalloc
es otra implementación independiente que reclama un rendimiento multihilo aún mejor que ptmalloc3
y varios otros asignadores. No se cómo funciona, y no parece haber ninguna documentación obvia, así que tendrás que revisar el código fuente para ver cómo funciona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:33:42