Buku Game Coding Complete, Edisi Keempat , bab 5 ( Inisialisasi Game dan Shutdown ), bagian Memeriksa Memori berisi contoh kode menarik ini:
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;
}
}
Ini menimbulkan beberapa pertanyaan.
Bagian pertama hanya bertanya pada OS (Windows) berapa banyak RAM fisik yang tersedia. Bagian yang ingin tahu adalah yang kedua, yang mengalokasikan sejumlah besar memori dan membebaskannya segera:
char *buff = GCC_NEW char[virtualRAMNeeded];
if (buff)
{
delete[] buff;
}
Penulis kemudian menjelaskan:
... fungsi ini mengalokasikan dan segera melepaskan blok memori yang besar. Ini memiliki efek membuat Windows membersihkan semua sampah yang menumpuk di manajer memori dan memeriksa ulang apakah Anda dapat mengalokasikan blok yang berdekatan seluas yang Anda butuhkan. Jika panggilan berhasil, Anda pada dasarnya menjalankan mesin yang setara dengan Zamboni melalui memori sistem Anda, menyiapkannya untuk gim Anda ...
Tapi saya punya keberatan tentang itu.
"Membersihkan sampah yang menumpuk di manajer memori?" Betulkah? Jika permainan baru saja dimulai, tidakkah seharusnya tidak ada sampah?
"Memastikan kamu bisa mengalokasikan blok yang berdekatan?" Dalam kasus yang sangat spesifik di mana Anda akan mengelola memori sendiri, ini akan membuat mereka masuk akal, tapi tetap saja, jika Anda mengalokasikan banyak memori langsung dari kelelawar, Anda cukup banyak membuat tidak mungkin untuk aplikasi lain berjalan di sistem saat sistem Anda aktif.
Juga, bukankah ini akan memaksa OS untuk melakukan semua memori itu, dan sebagai akibatnya mengusir banyak memori ke ruang swap disk, banyak memperlambat startup aplikasi Anda?
Apakah ini benar-benar praktik yang baik?
operator new
untuknullptr
), jika Anda mengizinkan saya untuk mengatakan. Hal terbaik yang dapat Anda lakukan dengan buku itu adalah menyalakan cerobong asap Anda. Mengalokasikan dan membebaskan blok memori yang besar tentu saja tidak "membersihkan" memori.new
operator global untuk mengembalikan nol daripada melemparbad_alloc
. Jika tidak, maka ya, kode ini bahkan lebih tidak masuk akal: Poperator delete
diperlukan untuk menerimanullptr
dan memperlakukannya sebagai larangan . Setiap kelebihan global yang tidak melakukan itu rusak. Yang artinya tidak masuk akal. Sama seperti mengasumsikan bahwa mengalokasikan sejumlah besar memori dan melepaskannya akan "secara ajaib" melakukan sesuatu yang baik. Paling-paling, itu tidak akan membahayakan (kemungkinan besar, karena halaman bahkan tidak disentuh ... kalau tidak, mungkin swap keluar beberapa halaman dari set kerja Anda yang Anda perlu memuat ulang nanti).Jawaban:
Satu hal yang pra-mengalokasikan sepotong besar memori bisa lakukan, jika komputer Anda rendah pada RAM, mungkin memaksa OS untuk membebaskan beberapa ruang tambahan dengan menukar bagian dari ruang memori program lain ke disk.
Karena bertukar seperti itu umumnya merupakan operasi yang sangat lambat yang cukup banyak membekukan program Anda saat itu terjadi, mungkin ada beberapa keuntungan untuk memastikan bahwa, jika itu akan terjadi, itu akan terjadi sebelum permainan Anda dimulai daripada di tengah-tengah gameplay.
Yang mengatakan, memaksa swap-ke-disk seperti ini tidak sepenuhnya dapat diandalkan 100%:
Pada banyak implementasi memori virtual, hanya mengalokasikan memori tidak benar-benar memicu swapping; melainkan, itu hanya terjadi ketika Anda pertama kali mengakses setiap halaman dari memori yang Anda alokasikan. (Hal ini tentu berlaku pada versi Linux modern, dengan memory overcommit diaktifkan, seperti pada umumnya; Saya tidak tahu pasti bagaimana berbagai versi Windows menanganinya.)
Jadi, jika Anda benar-benar ingin kode ini "membersihkan memori", Anda mungkin harus menambahkan
memset()
panggilan atau yang setara untuk benar-benar menulis data ke setiap bagian array (atau setidaknya denganphysicalRAMNeeded
byte pertama ) sebelum melepaskannya.Juga, memaksa OS untuk program pertukaran lainnya keluar dari RAM seperti ini tidak berarti bahwa mereka akan tetap keluar dari itu. Windows adalah OS multitasking, dan segera setelah salah satu dari program yang ditukar itu ingin berjalan kembali dan untuk menggunakan data yang ditukar, ia akan ditukar kembali, berpotensi membekukan permainan Anda lagi.
Dengan demikian, trik ini umumnya hanya berguna jika RAM sedang dimakan oleh potongan besar data yang tidak sedang diakses secara aktif (seperti dokumen besar dibiarkan terbuka di latar belakang dalam beberapa perangkat lunak pengeditan). Peramban web cenderung sangat bermasalah dalam hal ini, karena, bahkan jika Anda tidak benar-benar menggunakan laman web yang dibuka di beberapa tab latar belakang, laman tersebut mungkin masih memiliki skrip yang menjalankannya yang memaksanya disimpan dalam RAM.
(Ada beberapa cara bagi sebuah program untuk benar-benar memberi tahu OS untuk mengunci sebagian ruang memorinya ke dalam RAM dan mencegahnya ditukar, tetapi ini biasanya membutuhkan hak istimewa yang lebih tinggi. Dalam kasus apa pun, kode yang Anda posting tampaknya tidak menggunakan metode seperti itu.)
Pada dasarnya, trik ini tampaknya hanya berguna dalam situasi batas yang relatif sempit di mana pengguna akan memiliki cukup RAM untuk menjalankan game Anda (dan perangkat lunak lain yang aktif berjalan di latar belakang) tanpa bertukar, tetapi RAM saat ini diisi dengan file terbuka yang tidak aktif dan tidak digunakan. atau data lain yang dapat dan harus ditukar ke disk saat game Anda berjalan. Dalam situasi seperti itu, ini mungkin efektif dalam membuat game Anda tampak lebih halus dan lebih responsif, dengan mengganti operasi swap kecil sesekali selama bermain game dengan operasi tunggal selama startup.
sumber
Saya tidak tahu berapa usia luncuran itu, tapi saya katakan sudah cukup tua. Di Windows modern (XP dan yang lebih baru, tetapi khususnya pada versi 64-bit), saya akan mengatakan melakukan sesuatu seperti itu akan berdampak kecil pada permulaan gim Anda.
Pertama-tama, ingatlah bahwa ruang alamat divirtualisasi untuk setiap proses. Sejauh menyangkut proses Anda, Anda memiliki seluruh ruang alamat untuk diri Anda sendiri, dan Anda akan selalu mendapatkan memori yang bersebelahan (virtual), terlepas dari apakah memori itu bersebelahan secara fisik atau tidak.
Faktanya, apakah memori itu bersebelahan atau tidak dalam memori fisik bukanlah sesuatu yang Anda kontrol. OS akan memilih bagaimana mengalokasikan blok fisik sesuai keinginan, dan tidak ada yang Anda lakukan pada level aplikasi yang dapat memengaruhi manfaat (jika ada) memiliki memori fisik yang berdekatan.
Anda harus peduli dengan fragmentasi memori virtual jika Anda terus mengalokasikan dan membebaskan memori dari berbagai ukuran untuk waktu yang sangat lama. Ini tentu saja jauh kurang relevan dengan ruang alamat 64-bit. Gim biasanya tidak berjalan berbulan-bulan, jadi Anda kemungkinan besar tidak perlu peduli tentang ini, kecuali jika kita berbicara tentang server gim yang berjalan lama.
Bahkan jika Anda mengalokasikan banyak memori dengan ukuran yang sangat berbeda di mesin 32-bit, alokasi memori modern cukup bagus, sehingga tidak mungkin Anda akan mendapatkan masalah fragmentasi memori virtual kecuali jika Anda secara aktif mencari mereka
Jujur dengan Anda, saya tidak tahu apa yang sedang terjadi tentang penulis itu. Bahkan jika ruang alamat dibagikan, dan Anda mendapatkan blok besar yang berdekatan dalam memori fisik, dengan membebaskannya, Anda mengatakan Anda tidak peduli lagi. Ada program lain yang berjalan di latar belakang melakukan alokasi mereka sendiri, jadi bahkan jika malloc besar Anda berhasil, tidak ada yang akan menjamin yang berikutnya akan berhasil juga.
Saya pikir itu adalah kasus "itu berhasil karena suatu alasan saya tidak begitu mengerti, jadi saya membuat sesuatu untuk menjelaskannya".
sumber