Tienes razón, es un problema común [Es decir: cómo hacer la asignación de tamaño fijo, quiero decir. "malloc
está ralentizando mi aplicación" es menos común de lo que crees].
Si su código es demasiado lento y malloc
es un culpable plausible, entonces un simple asignador de celda (o "grupo de memoria") podría mejorar las cosas. Casi con certeza puede encontrar uno en alguna parte, o es fácil de escribir:
Asigne un bloque grande y coloque un nodo de lista enlazado individualmente al comienzo de cada celda de 16 bytes. Enlazarlos a todos juntos.Para asignar, quitar el encabezado de la lista y devolverlo. Para liberar, agregue la celda al encabezado de la lista. Por supuesto, si intentas asignar y la lista está vacía, entonces debes asignar un nuevo bloque grande, dividirlo en celdas y agregarlas a la lista libre.
Puede evitar ese gran trabajo por adelantado si lo desea. Cuando asigna un bloque grande, simplemente almacene un puntero hasta el final. Para asignar, mueva su puntero hacia atrás 16 bytes a través del bloque y devuelva el nuevo valor. A menos que ya estuviera al comienzo del bloque [*], por supuesto. Si eso sucede, y la lista gratuita también está vacía, necesita un nuevo bloque grande. Gratis no cambia: solo agrega el nodo a la lista gratuita.
Tiene la opción de tratar primero el bloque y consultar la lista gratuita si está agotada, o consultar primero la lista gratuita y ocuparse del bloque si está vacío. No sé cuál tiende a ser más rápido: lo bueno de la lista gratuita de último en entrar es que es compatible con el caché, ya que está usando memoria que se usó recientemente, así que probablemente lo intente. primero.
Tenga en cuenta que el nodo de la lista no es necesario mientras la celda está asignada, por lo que esencialmente hay cero sobrecarga por celda. Aparte de la velocidad, es probable que sea una ventaja sobre malloc
, u otros asignadores de propósito general.
Tenga en cuenta que soltar todo el asignador es prácticamente la única forma de liberar memoria al sistema, por lo que los usuarios que planean asignar una gran cantidad de celdas, usarlas y liberarlas, deben crear su propia asignador, úsalo y luego destrúyelo. Tanto para el rendimiento (no es necesario liberar todas las celdas) como para evitar el efecto de fragmentación en el que se debe mantener un bloque completo si alguna de sus celdas está en uso. Si no puede hacer esto, su uso de la memoria será la marca máxima del tiempo que su programa ha estado funcionando. Para algunos programas, eso es un problema (por ejemplo, un programa de larga ejecución con ocasionales picos grandes en el uso de memoria, en un sistema donde la memoria está restringida). Para otros, está absolutamente bien (por ejemplo, si la cantidad de células en uso aumenta hasta casi el final del programa, o fluctúa dentro de un rango en el que realmente no te importa que uses más memoria de la que estrictamente puedes). Para algunos es activamente deseable (si sabes cuánta memoria usarás, puedes asignarla por adelantado y no tener que preocuparte por los fallos). Para el caso, algunas implementaciones de malloc
tienen dificultades para liberar memoria del proceso al sistema operativo.
[*] Donde "inicio del bloque" probablemente signifique "el inicio del bloque, más el tamaño de un nodo utilizado para mantener una lista de todos los bloques, para que todos puedan liberarse cuando el asignador de celda sea destruido".
Va a necesitar esta memoria "una sola vez", como dicen por algún algoritmo o va a hacer esto en el transcurso de la tiempo de vida de los programas (¿qué puede ser muy largo?) – Skurmedel
Uno de los criterios al desarrollar una biblioteca de asignación es qué tan bien funcionará bajo este tipo de circunstancias, y bajo condiciones aún menos amistosas. Si bien la implementación de rutinas de asignación personalizadas es muy divertida, probablemente no la necesite. –
@Skurmedel: se solicitarán y liberarán muchos pedacitos de memoria durante la ejecución del programa. – mmmmalloc