He estado investigando la creación de mis propios métodos de asignación (que admitirán cosas como un grupo de memoria y creación de perfiles), sin embargo, a medida que continúo mi investigación, he estado buscando cómo se hizo esto en el desarrollo de juegos.
¿Qué técnica de asignación de memoria podría usar y por qué es una buena técnica?
Respuestas:
Game Engine Architecture tiene información sobre este tema. Lo básico es que necesita hacer un análisis para comprender cuáles son sus requisitos de memoria por nivel / marco / etc. son como, pero hay algunos patrones que el autor menciona haber visto varias veces:
Lo más importante que el autor menciona es la fragmentación de la memoria. Esto es un problema menor si está desarrollando para, por ejemplo, una PC donde tiene algún tipo de copia de seguridad de paginación de memoria con la que puede contar, pero en un contexto de memoria fija como una consola, existe el riesgo de estar "sin memoria" cuando intente asignar un objeto grande porque su memoria está fragmentada de tal manera que solo están disponibles pequeños bloques contiguos. Con ese fin, recomienda que un asignador basado en pila como el anterior también incluya un método para desfragmentar periódicamente su contenido.
Para obtener más información sobre el código real involucrado en esto, recomiendo el artículo de Christian Gyrling, "¿Nos hemos quedado sin memoria?" , que cubre técnicas para asignadores personalizados, principalmente desde una perspectiva de análisis de patrones de uso de memoria, pero esto también es aplicable para diseñar una solución personalizada para la administración de memoria.
fuente
Por lo que he visto (pero no hecho), cada juego tiende a heredar los mecanismos de asignación de un marco, de un motor de juego, de la versión anterior (2010 -> 2011) o obtiene un conjunto de nuevos escritos específicamente para su estructura (ya sea cuando las estructuras de datos son reutilizables y de tamaño fijo o de numerosos tipos y tamaños variables).
También teníamos diferentes asignadores para archivos / componentes de sonido que para niveles y otros objetos del juego en el mismo proyecto. En otros proyectos, los asignadores se heredan de bibliotecas externas solo para los componentes administrados por esa biblioteca.
La optimización realmente depende de sus necesidades. Pero generalmente la asignación se realiza antes de ingresar a la escena del juego y luego se reutiliza la memoria. Algunos juegos pueden salirse sin dar asignadores personalizados. Pero para los juegos de acción en los que se presupuestan los recursos del procesador, la memoria y los datos, no puede permitirse perder el tiempo de procesamiento en asignaciones grandes, no puede desperdiciar la memoria en la fragmentación y otros problemas.
Con respecto a los ejemplos, simplemente debe comenzar por echar un vistazo al motor de juego OGRE 3D , que tiene algunas opciones para configurar los asignadores de memoria.
fuente
El error que a menudo se comete es escribir sus propios asignadores para que pueda tener más control sobre la cantidad de memoria utilizada por cada sistema y tener más visibilidad sobre lo que está sucediendo. Una forma mucho mejor de lograr esto es usar un generador de perfiles de memoria. Hay muchos perfiladores de memoria, mi perfilador MemPro es un ejemplo. Esta es una forma totalmente no invasiva de realizar un seguimiento de todo el uso de la memoria, y puede dividirlo automáticamente en subsistemas utilizando filtros comodín callstack. Idealmente, es mejor mantener su asignación de memoria y seguimiento de memoria totalmente separados, tienen requisitos totalmente diferentes.
La división arbitraria de su memoria en grupos a menudo puede ser perjudicial porque cada grupo tendrá una sobrecarga. Puedes terminar usando mucha más memoria de la que necesitas sin darte cuenta. Para reducir el desperdicio siempre es mejor agrupar todo, la holgura es compartida por todo el sistema.
Las únicas razones para usar asignadores personalizados son el rendimiento de la CPU (principalmente para la coherencia de la memoria caché) y para limitar la fragmentación. Un ejemplo perfecto de esto es un sistema de partículas. Desea que todas las partículas sean contiguas en la memoria y no quiere sazonar la memoria principal con muchas asignaciones de corta duración. Otro buen ejemplo para la partición es un lenguaje de script.
Si desea un ejemplo de reemplazo de malloc de uso general, puede echar un vistazo a mi asignador VMem . Se ha utilizado en varios juegos AAA enviados. Tiene técnicas que limitan la fragmentación y mantienen baja la huella de memoria, algo crítico para los juegos de consola. También es muy rápido bajo alta contención de hilos. Mi sitio web tiene una amplia documentación sobre estas técnicas.
fuente