2010-11-27 14 views
9

¿Cuáles son mis opciones para minimizar la huella de memoria en los programas C en Linux (* nix)?Minimizando la huella de memoria en los programas C

Por lo que sé, libc malloc() está utilizando ya sea brk() o mmap(). La memoria asignada con brk() generalmente no se puede devolver debido a la fragmentación de la memoria.

Mi programa debería funcionar 24/7 y tiene una gran cantidad de malloc() - s y free() - s. Después de comenzar, RSS sube a aproximadamente 100Mb. Es demasiado, porque sé con certeza que en cualquier momento particular hay menos de 100 Mb de datos en la memoria.

Probablemente es un problema de fragmentación brk().

¿Cuáles son mis opciones aquí?

¿Debo usar otra implementación de malloc(), que solo usa mmap()? ¿Debo hacer algo más? ¿Hay algo que pueda leer sobre el problema de la huella de memoria?

Gracias.

Respuesta

11

Si su programa tiene tantas llamadas malloc y free que obtiene este tipo de fragmentación, usar mmap para cada asignación será irremediablemente lento. En su lugar, necesita medir qué está causando la fragmentación de la memoria y corregirla. Primero usaría una herramienta como valgrind para asegurarme de que no sea realmente un problema de fuga de memoria/corrupción que cause el uso excesivo de memoria. Luego, para confirmar que la causa del problema es la fragmentación, envolveré todas las llamadas a malloc y free con su propio contenedor que incrementa y disminuye una variable de "total de bytes asignados" para que pueda, en cualquier momento, comparar los valores teóricos y consumo real de memoria.

Si resulta que la fragmentación es el problema, un buen primer paso es ver por qué está haciendo tantas asignaciones pequeñas y de corta vida. Si puede eliminarlos y, en su lugar, asignar toda la memoria que un objeto/tarea de datos en particular necesitará en un solo bloque, entonces córtela usted mismo, no solo eliminará la peor fragmentación sino que también mejorará el rendimiento de su código. un poco. Cada llamada a malloc o free incurre en una buena sobrecarga, especialmente en un entorno con rosca donde es necesaria la sincronización/bloqueo. Mantener todos los datos asociados en un solo bloque asignado también puede reducir o eliminar la necesidad de escribir código especial para liberar estructuras que contienen punteros; una sola llamada al free a menudo puede ser suficiente (aunque para mantener la implementación opaca, debe envolver esto con una función foo_free).

+1

Usar 'mmap()' para cada asignación no solo sería lento, sino que probablemente incrementaría el uso de memoria, ya que cada asignación se redondea al tamaño de una página de memoria (al menos 4k en la mayoría de las plataformas). – alanc

+2

Básicamente, si tiene muchos allocs idénticos, marque su propio libreto de referencias y preasigne una tonelada de bloques.Aquí puedes encontrar un buen libre de cerradura; http://www.liblfds.org (declinación de interés: soy el autor). Acabo de hacer un punto de referencia de ese libre-freelist contra un libre-libre del mutex; ¡es 10 veces más rápido en un núcleo, 100 veces más rápido en dos! –

+0

Gracias. Definitivamente no está goteando. Investigaré más a fondo. –

2

A menos que esté asignando bloques de tamaño fijo o realizando algún tipo de recolección periódica de elementos no utilizados, es probable que la huella de memoria crezca más de lo necesario debido a la fragmentación.

free() no se puede devolver la memoria al sistema operativo a menos que no se utilicen páginas completas.

Mi sugerencia sería utilizar un esquema slab allocation. Preasigne varios grupos de memoria. Cada grupo se usará con objetos de tamaño similar (tamaño idealmente idéntico). De esta forma evitará la fragmentación y mantendrá su huella de RSS constante (aunque sea más grande que absolutamente necesario debido a la asignación previa).

Cuestiones relacionadas