Das Buch Game Coding Complete, 4. Auflage , Kapitel 5 ( Game Initialization and Shutdown ), Abschnitt Überprüfung des Speichers, enthält dieses interessante Codebeispiel:
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;
}
}
Dies wirft einige Fragen auf.
Der erste Teil fragt nur das Betriebssystem (Windows), wie viel physischer RAM verfügbar ist. Der merkwürdige Teil ist der zweite, der einen großen Teil des Speichers zuweist und ihn sofort freigibt:
char *buff = GCC_NEW char[virtualRAMNeeded];
if (buff)
{
delete[] buff;
}
Der Autor erklärt weiter:
... diese Funktion reserviert und gibt sofort einen riesigen Speicherblock frei. Dies bewirkt, dass Windows alle im Speichermanager angesammelten Abfälle bereinigt und überprüft, ob Sie einen zusammenhängenden Block so groß wie nötig zuordnen können. Wenn der Anruf erfolgreich ist, haben Sie im Wesentlichen das Äquivalent einer Zamboni-Maschine im Speicher Ihres Systems ausgeführt, um es für Ihr Spiel auf Eis zu legen ...
Aber ich habe meine Vorbehalte dazu.
Msgstr "Müll säubern, der sich im Speichermanager angesammelt hat?" "Ja wirklich?" Wenn das Spiel gerade erst begonnen hat, sollte es dann keinen Müll geben?
Msgstr "Sicherstellen, dass Sie einen zusammenhängenden Block zuordnen können?" In dem speziellen Fall, in dem Sie den Speicher selbst verwalten möchten, ist dies sinnvoll. Wenn Sie jedoch auf Anhieb viel Speicher zuweisen, können Sie praktisch keine andere Anwendung ausführen das System, während Ihr eingeschaltet ist.
Erzwingt dies wahrscheinlich nicht das Festschreiben des gesamten Arbeitsspeichers durch das Betriebssystem und folglich das Entfernen einer großen Menge Arbeitsspeichers auf den Swap-Speicher, wodurch der Start Ihrer App erheblich verlangsamt wird?
Ist das wirklich eine gute Übung?
operator new
auf überprüfendnullptr
), wenn Sie mir erlauben sagen. Das Beste, was Sie mit diesem Buch anfangen können, ist, Ihren Schornstein anzuzünden. Das Zuweisen und Freigeben eines großen Speicherblocks " räumt " natürlich nicht den Speicher auf.new
Operator zumindest überladen , um null zurückzugeben, anstatt zu werfenbad_alloc
. Wenn nicht, dann ist dieser Code noch unsinniger: Poperator delete
ist, muss es akzeptiertnullptr
und als No-Op behandelt werden. Jede globale Überladung, die das nicht tut, ist kaputt. Das heißt, es ist so oder so unsinnig. Genauso wie man annimmt, dass das Zuweisen und Freigeben eines riesigen Speicherblocks "magisch" etwas Gutes bewirkt. Im besten Fall schadet es nicht (höchstwahrscheinlich, da die Seiten nicht einmal berührt werden ... andernfalls werden möglicherweise einige Seiten aus Ihrem Arbeitsbereich ausgetauscht, die Sie später neu laden müssen).Antworten:
Eine Sache , die einen großen Teil des Speichers im Voraus zugeordnet könnte tun, wenn Ihr Computer war wenig RAM, könnte sein , das Betriebssystem zu zwingen , etwas mehr Platz zu schaffen durch Teile anderer Programme Speicherplatz auf der Festplatte austauschen.
Da ein solches Auswechseln in der Regel sehr langsam ist und Ihr Programm während des Spiels so gut wie einfriert, kann es von Vorteil sein, sicherzustellen, dass es, falls es trotzdem passieren sollte, vor dem Beginn Ihres Spiels und nicht mitten im Spielgeschehen stattfindet.
Das heißt, ein Swap-to-Disk wie dieses zu erzwingen, ist nicht gerade 100% zuverlässig:
Bei vielen Implementierungen von virtuellem Speicher wird durch das bloße Zuweisen von Speicher kein Swap ausgelöst. Dies geschieht nur, wenn Sie zum ersten Mal auf jede Seite des von Ihnen zugewiesenen Speichers zugreifen. (Dies trifft auf jeden Fall auf moderne Linux-Versionen zu, bei denen die Speicherüberlastung standardmäßig aktiviert ist. Ich weiß nicht genau, wie die verschiedenen Windows-Versionen damit umgehen.)
Wenn Sie also wirklich möchten, dass dieser Code den Speicher aufräumt, sollten Sie wahrscheinlich einen
memset()
Aufruf oder eine Entsprechung hinzufügen , um Daten in jeden Teil des Arrays (oder zumindest in die erstenphysicalRAMNeeded
Bytes davon) zu schreiben, bevor Sie ihn freigeben.Außerdem zwingt das Betriebssystem zu tauschen andere Programme aus dem RAM wie dies bedeutet nicht , dass sie dann bleiben davon aus. Windows ist ein Multitasking-Betriebssystem, und sobald eines dieser ausgelagerten Programme erneut ausgeführt und die ausgelagerten Daten verwendet werden sollen, wird es wieder eingelagert, wodurch das Spiel möglicherweise erneut eingefroren wird.
Daher ist dieser Trick im Allgemeinen nur nützlich, wenn der RAM von großen Datenmengen aufgebraucht wird, auf die nicht aktiv zugegriffen wird (z. B. große Dokumente, die in einigen Bearbeitungssoftware im Hintergrund offen gelassen werden). Webbrowser sind in dieser Hinsicht in der Regel besonders problematisch, da auf der Seite möglicherweise noch Skripts ausgeführt werden, die das Speichern im RAM erzwingen, auch wenn Sie keine Webseite verwenden, die auf einer Hintergrundregisterkarte geöffnet wurde.
(Es gibt Möglichkeiten, mit denen ein Programm das Betriebssystem anweist, einen Teil seines Speicherplatzes im RAM zu sperren und das Auslagern zu verhindern. Dies erfordert jedoch in der Regel erhöhte Berechtigungen. In jedem Fall scheint der von Ihnen bereitgestellte Code nicht zu sein mit solchen Methoden.)
Grundsätzlich scheint dieser Trick nur sinnvoll , in dieser relativ engen Grenzsituation , wo der Benutzer würde genug RAM Spiel (und andere Software aktiv im Hintergrund laufen) ohne Austausch, aber das RAM ist derzeit gefüllt mit inaktiven und nicht verwendeten offenen Dateien zu laufen oder andere Daten, die während des Spiels auf die Festplatte übertragen werden können und sollten. In solchen Situationen kann es hilfreich sein, Ihr Spiel flüssiger und reaktionsschneller erscheinen zu lassen, indem gelegentliche kleine Tauschoperationen während des Spiels durch eine einzige während des Startvorgangs ersetzt werden.
quelle
Ich weiß nicht, wie alt das ist, aber ich würde sagen, es ist ziemlich alt. In modernen Windows-Versionen (XP und neuer, aber speziell in 64-Bit-Versionen) würde ich sagen, dass eine solche Vorgehensweise den Start Ihres Spiels kaum negativ beeinflusst.
Denken Sie zunächst daran, dass der Adressraum für jeden Prozess virtualisiert wird. Für Ihren Prozess steht Ihnen der gesamte Adressraum zur Verfügung, und Sie erhalten immer zusammenhängenden (virtuellen) Speicher, unabhängig davon, ob dieser physisch zusammenhängend ist oder nicht.
In der Tat haben Sie keinen Einfluss darauf, ob der Speicher im physischen Speicher zusammenhängend ist oder nicht. Das Betriebssystem wählt aus, wie die physischen Blöcke zugewiesen werden sollen, und nichts, was Sie auf Anwendungsebene tun, kann sich auf die Vorteile (falls vorhanden) eines zusammenhängenden physischen Speichers auswirken.
Sie müssen sich um die Fragmentierung des virtuellen Speichers kümmern, wenn Sie weiterhin sehr lange Speicher unterschiedlicher Größe zuweisen und freigeben. Dies ist natürlich bei einem 64-Bit-Adressraum weniger relevant. Spiele werden in der Regel nicht monatelang ausgeführt, sodass Sie sich höchstwahrscheinlich nicht darum kümmern müssen, es sei denn, es handelt sich um Server mit langer Laufzeit.
Selbst wenn Sie in einem 32-Bit-Computer viel Speicher mit sehr unterschiedlichen Größen zuweisen, ist die Speicherzuweisung in der heutigen Zeit recht gut. Daher ist es unwahrscheinlich, dass Probleme mit der Fragmentierung des virtuellen Speichers auftreten, wenn Sie nicht aktiv danach suchen
Um ehrlich zu sein, ich weiß nicht, worum es bei diesem Schriftsteller geht. Selbst wenn der Adressraum gemeinsam genutzt wurde und Sie einen riesigen zusammenhängenden Block im physischen Speicher erhalten haben, sagen Sie, dass Sie sich nicht mehr darum kümmern, indem Sie ihn freigeben. Im Hintergrund werden andere Programme ausgeführt, die ihre eigenen Zuordnungen vornehmen. Selbst wenn Ihr großes Einkaufszentrum erfolgreich ist, kann niemand garantieren, dass das nächste Programm ebenfalls erfolgreich ist.
Ich denke, das ist ein Fall von "es hat aus irgendeinem Grund funktioniert, den ich nicht wirklich verstehe, also habe ich mir etwas ausgedacht, um es zu erklären".
quelle