2011-01-16 16 views
10

Leo que algunos juegos reescriben su propio malloc para ser más eficientes. No entiendo cómo esto es posible en un mundo de memoria virtual. Si recuerdo correctamente, malloc realmente llama a una función específica del sistema operativo, que asigna la dirección virtual a una dirección real con la MMU. Entonces, ¿cómo puede alguien hacer su propio asignador de memoria y asignar memoria real sin llamar al malloc del tiempo de ejecución real?haciendo su propia función malloc?

Gracias

+5

es más probable que estén preasignando un gran bloque de memoria (una "arena de memoria") que evita la fragmentación y permite un mejor rendimiento de asignación – BrokenGlass

+0

Sí, puede solicitar al sistema operativo una gran porción de memoria contigua Milo. Es bastante común en el mundo de los sistemas. –

+0

Sí, lo más probable es que escriban un envoltorio alrededor de malloc que usan en lugar de llamar malloc directamente, lo que aumenta la velocidad en algunos casos, pero no reemplaza las cosas de nivel de sistema operativo –

Respuesta

8

Es ciertamente posible escribir un asignador más eficiente que uno de propósito general.

Si conoce las propiedades de sus asignaciones, puede hacer que los asignadores de uso general salgan del agua.

Ejemplo: muchos años atrás, tuvimos que diseñar y codificar un subsistema de comunicación (HDLC, X.25 y capas propietarias) para sistemas integrados. El hecho de que sabíamos que la asignación máxima siempre sería inferior a 128 bytes (o algo así) significaba que no teníamos que perder el tiempo con bloques de tamaño variable. Cada asignación de era de 128 bytes, sin importar cuánto pidiera.

Por supuesto, si solicitó más, devolvió NULL.

Al usar bloques de longitud fija, pudimos acelerar en gran medida las asignaciones y las desasignaciones, utilizando mapas de bits y estructuras asociadas para mantener la información de contabilidad en lugar de depender de listas vinculadas más lentas. Además, la necesidad de unir bloques liberados no era necesaria.

De acuerdo, este fue un caso especial, pero también lo es para los juegos. De hecho, incluso hemos utilizado esto en un sistema de propósito general en el que las asignaciones por debajo de cierto umbral obtuvieron una cantidad fija de memoria de un grupo preasignado autogestionado hecho de la misma manera. Cualquier otra asignación (más grande que el umbral o si el grupo se asignó por completo) se envió a la "real" malloc.

+0

Un asignador de propósito general que utiliza los algoritmos de binning correctos es igual de rápido y mucho más poderoso siempre que no tenga que lidiar con trapos. Sin embargo, les garantizo que sus bitmaps podrían ser más rápidos y/o simples una vez que entre en juego la concurrencia. –

+1

Un asignador de propósito general casi siempre (creo que siempre es siempre, yo mismo, pero no seré tan arrogante) ser derrotado por uno que tiene la ventaja de un conocimiento extra. Yendo a lo largo de la línea reductio ad absurdum, si sabe que solo una asignación estará activa a la vez y siempre será menor que 1K, puede tener un búfer estático en su malloc :-) No hay _no_ asignador binning que pueda superan eso. Tienes razón en que es una compensación, flexibilidad contra la velocidad, pero de ahí viene la pregunta: los juegos probablemente no necesiten toda esa flexibilidad. – paxdiablo

+4

Escribí un estudio exhaustivo sobre este tema. El punto principal es que los beneficios de rendimiento de los asignadores de memoria personalizados suelen ser inferiores a los anunciados cuando se comparan con un asignador de memoria de última generación. Ver http://www.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf – EmeryBerger

2

Una cosa que puede hacer es tener el asignador asigna una piscina de la memoria, luego de que las solicitudes de servicio (y asignar una piscina más grande si se agota). No estoy seguro de si eso es lo que están haciendo.

3

El hecho de que malloc() sea una función C estándar no significa que sea el acceso de menor nivel al sistema de memoria. De hecho, malloc() probablemente se implemente en términos de funcionalidad de sistema operativo de nivel inferior. Eso significa que también puedes llamar a esas interfaces de nivel inferior. Pueden ser específicos del sistema operativo, pero pueden permitirle un mejor rendimiento del que obtendría de la interfaz malloc(). Si ese fuera el caso, podría implementar su propio sistema de asignación de memoria de la forma que desee, y tal vez ser aún más eficiente al respecto, optimizando el algoritmo para las características del tamaño y la frecuencia de las asignaciones que va a realizar, por ejemplo .

3

En general, malloc llamará a una función específica del sistema operativo para obtener una gran cantidad de memoria (al menos una página VM), y luego dividirá esa memoria en trozos más pequeños según sea necesario para volver al llamador de malloc.

La biblioteca malloc también tendrá una lista (o listas) de bloques libres, por lo que a menudo puede cumplir una solicitud sin pedir más memoria al sistema operativo. Determinar cuántos tamaños de bloque diferentes manejar, decidir si intentar combinar bloques libres adyacentes, etc., son las opciones que el implementador de la biblioteca malloc debe tomar.

Es posible omitir la biblioteca malloc e invocar directamente la función "darme algo de memoria" de nivel de sistema operativo y hacer su propia asignación/liberación en la memoria que obtiene del sistema operativo. Tales implementaciones son probablemente específicas del sistema operativo. Otra alternativa es usar malloc para las asignaciones iniciales, pero mantenga su propio caché de objetos liberados.

2

Si no recuerdo mal, en realidad malloc llama a una función específica del sistema operativo

No del todo. La mayoría del hardware tiene un tamaño de página de 4KB. Los sistemas operativos generalmente no exponen una interfaz de asignación de memoria que ofrezca algo más pequeño que los fragmentos de tamaño de página (y alineado con la página).

malloc pasa la mayor parte de su tiempo a administrar el espacio de memoria virtual que ya ha sido asignado, y sólo de vez en cuando pide más memoria desde el sistema operativo (obviamente esto depende del tamaño de los elementos que asignar y la frecuencia con que free).

Existe la idea errónea de que cuando se free algo se devuelve inmediatamente al sistema operativo. Si bien esto ocurre a veces (especialmente en el caso de bloques de memoria más grandes), generalmente la memoria free d permanece asignada al proceso y luego puede ser reutilizada por malloc s posteriores.

Por lo tanto, la mayor parte del trabajo consiste en la contabilidad del espacio virtual ya asignado. Las estrategias de asignación pueden tener muchos objetivos, como operación rápida, pérdida de memoria baja, buena localidad, espacio para crecimiento dinámico (por ejemplo, realloc) y así sucesivamente.

Si conoce más sobre su patrón de asignación y liberación de memoria, puede optimizar malloc y free para sus patrones de uso o proporcionar una interfaz más extensa.

Por ejemplo, puede asignar muchos objetos del mismo tamaño, lo que puede cambiar los parámetros de asignación óptimos. O siempre puede liberar grandes cantidades de objetos a la vez, en cuyo caso no desea que free haga cosas extravagantes.

Eche un vistazo a memory pools y obstacks.

Cuestiones relacionadas