El libro Game Coding Complete, Cuarta edición , capítulo 5 ( Inicialización y apagado del juego ), sección Checking Memory contiene este interesante ejemplo de código:
bool CheckMemory(const DWORDLONG physicalRAMNeeded, const DWORDLONG virtualRAMNeeded)
{
MEMORYSTATUSEX status;
GlobalMemoryStatusEx(&status);
if (status.ullTotalPhys < physicalRAMNeeded)
{
// you don’t have enough physical memory. Tell the player to go get a
// real computer and give this one to his mother.
GCC_ERROR("CheckMemory Failure: Not enough physical memory.");
return false;
}
// Check for enough free memory.
if (status.ullAvailVirtual < virtualRAMNeeded)
{
// you don’t have enough virtual memory available.
// Tell the player to shut down the copy of Visual Studio running in the
// background, or whatever seems to be sucking the memory dry.
GCC_ERROR("CheckMemory Failure: Not enough virtual memory.");
return false;
}
char *buff = GCC_NEW char[virtualRAMNeeded];
if (buff)
{
delete[] buff;
}
else
{
// even though there is enough memory, it isn't available in one
// block, which can be critical for games that manage their own memory
GCC_ERROR("CheckMemory Failure: Not enough contiguous memory.");
return false;
}
}
Esto plantea algunas preguntas.
La primera parte solo le pregunta al sistema operativo (Windows) cuánta RAM física está disponible. La parte curiosa es la segunda, que asigna una gran cantidad de memoria y la libera de inmediato:
char *buff = GCC_NEW char[virtualRAMNeeded];
if (buff)
{
delete[] buff;
}
El autor continúa explicando:
... esta función asigna e inmediatamente libera un gran bloque de memoria. Esto tiene el efecto de hacer que Windows limpie cualquier basura que se haya acumulado en el administrador de memoria y verifique que pueda asignar un bloque contiguo tan grande como lo necesite. Si la llamada tiene éxito, esencialmente ha ejecutado el equivalente de una máquina Zamboni a través de la memoria de su sistema, preparándolo para que su juego llegue al hielo ...
Pero tengo mis reservas sobre eso.
"¿Limpiar la basura acumulada en el administrador de memoria?" De Verdad? Si el juego acaba de comenzar, ¿no debería haber basura?
"¿Asegurándote de que puedes asignar un bloque contiguo?" En el caso muy específico en el que va a administrar la memoria usted mismo, esto tendría algún sentido, pero aún así, si asigna mucha memoria directamente, es casi imposible que se ejecute cualquier otra aplicación. el sistema mientras el tuyo está encendido.
Además, ¿no es probable que esto obligue al sistema operativo a comprometer toda esa memoria y, como consecuencia, expulsar una gran cantidad de memoria en el espacio del disco de intercambio, ralentizando mucho el inicio de la aplicación?
¿Es realmente una buena práctica?
operator new
anullptr
), si me lo permiten decir. Lo mejor que puedes hacer con ese libro es encender tu chimenea. Asignar y liberar un gran bloque de memoria, por supuesto , no "limpia" la memoria.new
operador global para que devuelva nulo en lugar de tirarbad_alloc
. Si no lo hicieron, entonces sí, este código es aún más absurdo: Poperator delete
es necesario aceptarlonullptr
y tratarlo como no operativo. Cualquier sobrecarga global que no haga eso está rota. Lo que significa que no tiene sentido de ninguna manera. Al igual que asumir que asignar un gran bloque de memoria y liberarlo "mágicamente" hará algo bueno. En el mejor de los casos, no hará ningún daño (lo más probable, ya que las páginas ni siquiera se tocan ... de lo contrario, puede cambiar algunas páginas de su conjunto de trabajo que deberá volver a cargar más adelante).Respuestas:
Una cosa que podría hacer la asignación previa de una gran cantidad de memoria , si su computadora tenía poca RAM, podría ser forzar al sistema operativo a liberar algo de espacio adicional intercambiando partes del espacio de memoria de otros programas en el disco.
Dado que tal intercambio es generalmente una operación muy lenta que congela su programa mientras está sucediendo, podría haber alguna ventaja para garantizar que, si va a suceder de todos modos, sucederá antes de que comience su juego en lugar de estar en el medio del juego.
Dicho esto, forzar un intercambio a disco como este no es exactamente 100% confiable:
En muchas implementaciones de memoria virtual, la simple asignación de memoria en realidad no desencadena ningún intercambio; más bien, solo sucede cuando accede por primera vez a cada página de la memoria que asignó. (Esto es cierto en las versiones modernas de Linux, con el exceso de memoria habilitado, como lo es por defecto; no estoy seguro de cómo las manejan las diferentes versiones de Windows).
Por lo tanto, si realmente desea que este código "limpie la memoria", probablemente debería agregar una
memset()
llamada o equivalente para escribir datos en cada parte de la matriz (o al menos en los primerosphysicalRAMNeeded
bytes) antes de liberarla.Además, obligar al sistema operativo a intercambiar otros programas de la RAM de esta manera no significa que se mantendrán al margen . Windows es un sistema operativo multitarea, y tan pronto como uno de esos programas intercambiados quiera volver a ejecutarse y usar sus datos intercambiados, volverá a conectarse, lo que podría congelar su juego nuevamente.
Por lo tanto, este truco generalmente solo es útil si la memoria RAM está siendo absorbida por grandes cantidades de datos a los que no se accede activamente (como documentos grandes que quedan abiertos en segundo plano en algún software de edición). Los navegadores web tienden a ser particularmente problemáticos a este respecto, ya que, incluso si no está utilizando una página web abierta en alguna pestaña de fondo, la página aún puede tener secuencias de comandos ejecutándose que obligan a mantenerla en la RAM.
(No son maneras para que un programa de realidad decirle al sistema operativo para bloquear una parte de su espacio de memoria en la memoria RAM y evitar que ser llevados a swap, pero éstos normalmente requieren privilegios elevados. En cualquier caso, el código que envió no parece estar usando cualquiera de estos métodos.)
Básicamente, este truco solo parece útil en esa situación límite relativamente estrecha en la que el usuario tendría suficiente RAM para ejecutar su juego (y cualquier otro software que se ejecute activamente en segundo plano) sin intercambiar, pero esa RAM está actualmente llena de archivos abiertos inactivos y no utilizados u otros datos que pueden y deben intercambiarse en el disco mientras se ejecuta el juego. En tales situaciones, puede ser efectivo para hacer que su juego parezca más fluido y receptivo, al reemplazar ocasionalmente pequeñas operaciones de intercambio durante el juego con una sola durante el inicio.
fuente
No sé cuántos años tiene ese escrito, pero diría que es bastante viejo. En Windows moderno (XP y más reciente, pero especialmente en versiones de 64 bits), diría que hacer algo así tendrá poco o un impacto negativo en el inicio de su juego.
En primer lugar, recuerde que el espacio de direcciones está virtualizado para cada proceso. En lo que respecta a su proceso, tiene todo el espacio de direcciones para usted y siempre obtendrá memoria contigua (virtual), independientemente de si esa memoria es físicamente contigua o no.
De hecho, si la memoria es contigua o no en la memoria física no es algo sobre lo que tenga control. El sistema operativo elegirá cómo asignar los bloques físicos como mejor le parezca, y nada de lo que haga a nivel de aplicación puede afectar los beneficios (si los hay) de tener memoria física contigua.
Debe preocuparse por la fragmentación de la memoria virtual si sigue asignando y liberando memoria de diferentes tamaños durante un período de tiempo muy largo. Por supuesto, esto es mucho menos relevante con un espacio de direcciones de 64 bits. Los juegos generalmente no se ejecutan durante meses, por lo que es probable que no tenga que preocuparse por esto, a menos que estemos hablando de servidores de juegos de larga duración.
Incluso si asigna mucha memoria de tamaños muy diferentes en una máquina de 32 bits, las asignaciones de memoria modernas son bastante buenas, por lo que es poco probable que tenga problemas de fragmentación de memoria virtual a menos que los esté buscando activamente
Para ser honesto contigo, no sé de qué está hablando ese escritor. Incluso si el espacio de direcciones fue compartido, y usted obtuvo un gran bloque contiguo en la memoria física, al liberarlo, está diciendo que ya no le importa. Hay otros programas que se ejecutan en segundo plano haciendo sus propias asignaciones, por lo que incluso si su gran malloc tuvo éxito, nadie garantizará que el próximo tenga éxito también.
Creo que es un caso de "funcionó por alguna razón que realmente no entiendo, así que hice algo para explicarlo".
fuente