การจัดสรรและเพิ่มหน่วยความจำขนาดใหญ่เมื่อเริ่มต้นใช้งาน“ ล้างหน่วยความจำหรือไม่”


18

หนังสือเกมการเข้ารหัสเสร็จสมบูรณ์ฉบับที่สี่บทที่ 5 (การเริ่มต้นเกมและการปิดระบบ ) ส่วนการตรวจสอบหน่วยความจำมีตัวอย่างโค้ดที่น่าสนใจนี้:

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;
    }
}

นี่ทำให้บางคำถาม

ส่วนแรกจะถามระบบปฏิบัติการ (Windows) ว่ามีฟิสิคัลแรมพร้อมใช้งานเท่าใด ส่วนที่อยากรู้อยากเห็นคือส่วนที่สองซึ่งจัดสรรหน่วยความจำขนาดใหญ่และปลดปล่อยมันทันที:

char *buff = GCC_NEW char[virtualRAMNeeded]; 
if (buff)
{
    delete[] buff;
}

ผู้เขียนอธิบายต่อไป:

... ฟังก์ชั่นนี้จัดสรรและปล่อยหน่วยความจำขนาดใหญ่ทันที นี่เป็นผลของการทำให้ Windows ล้างขยะใด ๆ ที่สะสมในตัวจัดการหน่วยความจำและตรวจสอบอีกครั้งว่าคุณสามารถจัดสรรบล็อกที่ต่อเนื่องได้ขนาดใหญ่เท่าที่คุณต้องการ หากการโทรสำเร็จคุณจะต้องใช้งานเครื่องเทียบเท่า Zamboni ผ่านหน่วยความจำของระบบเพื่อเตรียมพร้อมสำหรับเกมของคุณที่จะโจมตีน้ำแข็ง ...

แต่ฉันมีการจองของฉันในที่

"กำลังทำความสะอาดขยะที่สะสมในตัวจัดการหน่วยความจำใช่ไหม" จริงๆ? หากเกมเพิ่งเริ่มต้นขึ้นไม่ควรมีขยะหรือไม่

"ทำให้แน่ใจว่าคุณสามารถจัดสรรบล็อกที่ต่อเนื่องกันได้หรือไม่" ในกรณีที่เฉพาะเจาะจงมากที่คุณจะจัดการหน่วยความจำด้วยตัวเองสิ่งนี้จะทำให้เกิดความรู้สึก แต่ถ้าคุณจัดสรรหน่วยความจำด้านขวาของไม้ตีจำนวนมากคุณจะทำให้มันเป็นไปไม่ได้ที่แอพพลิเคชันอื่นจะทำงาน ระบบขณะที่คุณเปิดอยู่

นอกจากนี้ยังไม่มีแนวโน้มที่จะบังคับให้ระบบปฏิบัติการใช้หน่วยความจำทั้งหมดนั้นและดังนั้นจึงมีการส่งหน่วยความจำจำนวนมากไปยังพื้นที่ดิสก์ swap ทำให้การเริ่มต้นแอปของคุณช้าลงมาก?

นี่เป็นวิธีปฏิบัติที่ดีจริง ๆ หรือไม่?


3
ส่วนใหญ่ระบบปฏิบัติการที่ทันสมัยจะทำอะไรใด ๆ เมื่อมีการจัดสรรแอปพื้นที่ขนาดใหญ่ของหน่วยความจำที่พวกเขาใช้การจัดสรรในแง่ดีและไม่จริงทำอะไรจนกว่าคุณจะเติมเต็มหน่วยความจำที่ฉันไม่สามารถจินตนาการนี้ทำอะไรมากไปกว่าการเป็นที่อาจเกิดขึ้นช้า-op
Vality

การล้างพื้นดินที่มีความยาวในป่าการแกะสลักวิทยุหูฟังและอื่น ๆ จากไม้ส่งผลให้เครื่องบินลงจอดและส่งเสบียงหรือไม่?
Dan Neely

10
การเข้ารหัสเกมสมบูรณ์ประกอบด้วยเรื่องไร้สาระจำนวนมากที่จับคู่กับความไม่เข้าใจ -C ++ และ C-that-look-a-bit-like-C ++ (แสดงให้เห็นในตัวอย่างนี้การตรวจสอบผลลัพธ์operator newสำหรับnullptr) ถ้าคุณอนุญาตให้ฉัน เพื่อพูด. สิ่งที่ดีที่สุดที่คุณสามารถทำได้กับหนังสือเล่มนี้คือปล่องไฟของคุณ แน่นอนว่าการจัดสรรและเพิ่มหน่วยความจำขนาดใหญ่นั้นไม่ใช่การล้างหน่วยความจำ
Damon

@Damon ผมไม่ได้ตรวจสอบ แต่ผมสงสัยว่าพวกเขาได้อย่างน้อยเกินไปทั่วโลกnewผู้ประกอบการที่จะกลับ null bad_allocแทนการขว้างปา หากพวกเขาทำไม่ได้ใช่แล้วรหัสนี้ไร้สาระยิ่งกว่า: P
glampert

1
@glampert: แม้จะสมมติว่าเป็นกรณีนี้operator deleteก็จำเป็นต้องยอมรับnullptrและปฏิบัติต่อมันเป็นแบบไม่มี op การโอเวอร์โหลดทั่วโลกใด ๆ ที่ไม่ได้ทำนั้นเสียหาย ซึ่งหมายความว่ามันไร้สาระทั้งสองวิธี เช่นเดียวกับสมมติว่าการจัดสรรหน่วยความจำขนาดใหญ่และปล่อยมันจะ "น่าอัศจรรย์" ทำสิ่งที่ดี อย่างดีที่สุดมันจะไม่ทำอันตรายใด ๆ (น่าจะเป็นเพราะหน้าเว็บไม่ได้แตะเลย ... มิฉะนั้นมันอาจสลับหน้าบางส่วนจากชุดการทำงานของคุณซึ่งคุณจะต้องโหลดซ้ำในภายหลัง)
Damon

คำตอบ:


12

สิ่งหนึ่งที่การจัดสรรหน่วยความจำขนาดใหญ่ล่วงหน้าสามารถทำได้หากคอมพิวเตอร์ของคุณมี RAM น้อยอาจทำให้ระบบปฏิบัติการเพิ่มพื้นที่ว่างบางส่วนโดยการสลับส่วนของพื้นที่หน่วยความจำของโปรแกรมอื่นไปยังดิสก์

เนื่องจากการสลับเช่นนั้นเป็นการดำเนินการที่ช้ามากซึ่งค้างโปรแกรมของคุณในขณะที่มันเกิดขึ้นจึงอาจมีข้อได้เปรียบบางอย่างที่จะทำให้มั่นใจได้ว่าถ้ามันจะเกิดขึ้นต่อไปมันจะเกิดขึ้นก่อนที่เกมของคุณจะเริ่ม

ที่กล่าวว่าการบังคับ swap-to-disk เช่นนี้ไม่น่าเชื่อถือ 100%:

  • ในการใช้งานหน่วยความจำเสมือนมากมายการจัดสรรหน่วยความจำไม่ได้ทำให้เกิดการแลกเปลี่ยน ค่อนข้างจะเกิดขึ้นเมื่อคุณเข้าถึงหน่วยความจำที่คุณจัดสรรแต่ละหน้าเป็นครั้งแรก (นี่เป็นเรื่องจริงใน Linux รุ่นใหม่โดยมีการเปิดใช้งานหน่วยความจำเกินจริงเนื่องจากเป็นค่าเริ่มต้นฉันไม่รู้ว่า Windows รุ่นต่าง ๆ จัดการกับมันอย่างไร)

    ดังนั้นหากคุณต้องการให้รหัสนี้เป็น "ล้างหน่วยความจำ" คุณควรเพิ่มการmemset()โทรหรือเทียบเท่าเพื่อเขียนข้อมูลลงในทุก ๆ ส่วนของอาร์เรย์ (หรืออย่างน้อยต้องphysicalRAMNeededเท่ากับไบต์แรกของมัน) ก่อนที่จะปล่อยออกมา

  • นอกจากนี้ยังบังคับให้ระบบปฏิบัติการเพื่อแลกเปลี่ยนโปรแกรมอื่น ๆ ออกจาก RAM เช่นนี้ไม่ได้หมายความว่าพวกเขาจะอยู่ออกมาจากมัน Windows เป็นระบบปฏิบัติการมัลติทาสกิ้งและทันทีที่หนึ่งในโปรแกรมที่สลับสับเปลี่ยนต้องการรันอีกครั้งและใช้ข้อมูลที่สลับสับเปลี่ยนมันจะได้รับการสับเปลี่ยนกลับเข้ามาอาจทำให้เกมของคุณค้างอีกครั้ง

    ดังนั้นเคล็ดลับนี้จะมีประโยชน์เฉพาะในกรณีที่ RAM กำลังถูกกินโดยข้อมูลจำนวนมากที่ไม่ได้รับการเข้าถึงอย่างแข็งขัน (เช่นเอกสารขนาดใหญ่ที่เปิดทิ้งไว้ในพื้นหลังในซอฟต์แวร์แก้ไขบางอย่าง) เว็บเบราว์เซอร์มักจะมีปัญหาโดยเฉพาะอย่างยิ่งในเรื่องนี้เนื่องจากแม้ว่าคุณจะไม่ได้ใช้หน้าเว็บที่เปิดในแท็บพื้นหลังบางหน้าหน้าอาจยังคงมีสคริปต์ที่ทำงานอยู่ซึ่งบังคับให้เก็บไว้ใน RAM

    (มีเป็นวิธีสำหรับโปรแกรมที่จริงบอก OS เพื่อล็อคส่วนหนึ่งของพื้นที่หน่วยความจำของมันเข้าไปใน RAM และป้องกันไม่ให้มันจากการถูกสลับออก แต่เหล่านี้มักจะต้องยกระดับสิทธิ์. ในกรณีใด ๆ รหัสที่คุณโพสต์ไม่ได้ดูเหมือนจะเป็น ใช้วิธีการดังกล่าว)

โดยทั่วไปแล้วเคล็ดลับนี้มีประโยชน์เฉพาะในสถานการณ์เส้นขอบที่ค่อนข้างแคบซึ่งผู้ใช้จะมี RAM เพียงพอที่จะรันเกมของคุณ (และซอฟต์แวร์อื่น ๆ ที่ทำงานอยู่เบื้องหลัง) โดยไม่ต้องสลับ แต่ RAM นั้นเต็มไปด้วยไฟล์เปิดที่ไม่ได้ใช้งาน หรือข้อมูลอื่น ๆ ที่สามารถและควรเปลี่ยนเป็นดิสก์ในขณะที่เกมของคุณทำงานอยู่ ในสถานการณ์เช่นนี้มันอาจจะมีประสิทธิภาพในการทำให้เกมของคุณดูราบรื่นและตอบสนองมากขึ้นโดยการแทนที่การสลับเล็ก ๆ เป็นครั้งคราวในระหว่างการเล่นเกมด้วยการสลับระหว่างการเริ่มต้น


1
จากความรู้ที่ จำกัด ของฉันเกี่ยวกับการจัดการหน่วยความจำระดับต่ำฉันสามารถพูดได้ว่าการตัดสินใจว่าจะสลับหน้าเฉพาะเจาะจงมีความซับซ้อนมากขึ้นหรือไม่และคำนึงถึงปัจจัยอื่น ๆ อีกมากมายกว่าจำนวนหน่วยความจำที่ร้องขอและจำนวนหน่วยความจำที่มี . การทำอย่างนี้เกินขนาดและโดยทั่วไปการพึ่งพาการสนับสนุนนั้นไม่ได้ฉลาดนัก
แพนด้า Pyjama

3
ฉันคิดว่ามันเป็นสิ่งสำคัญที่จะต้องจำไว้ว่าสิ่งเหล่านี้ทั้งหมดเป็น suppositions ที่อาจใช้งานไม่ได้ทำงานหรือดูเหมือนจะทำงาน แต่ด้วยเหตุผลที่ไม่เกี่ยวข้องอย่างสมบูรณ์ เท่าที่ฉันรู้ไม่มีพฤติกรรมใดที่ชี้ให้เห็นในคำตอบนี้เป็นเอกสารและมันก็ไม่ฉลาดที่จะพึ่งพาพวกเขา การอัปเดตระบบปฏิบัติการการเปลี่ยนแปลงการตั้งค่าการเปลี่ยนแปลงคอมไพเลอร์หรืออะไรก็ตามที่ทำให้การทำงานหยุดชะงักหรือมีผลกระทบด้านลบต่อประสิทธิภาพการทำงาน
แพนด้า Pajama

26

ฉันไม่ทราบว่าการเขียนนั้นอายุเท่าไหร่ แต่ฉันบอกว่ามันค่อนข้างเก่า ใน Windows รุ่นใหม่ (XP และใหม่กว่า แต่โดยเฉพาะกับรุ่น 64 บิต) ฉันจะบอกว่าการทำบางอย่างเช่นนั้นจะส่งผลเสียต่อการเริ่มต้นเกมของคุณเล็กน้อย

ก่อนอื่นให้จำไว้ว่าพื้นที่ที่อยู่นั้นเสมือนจริงสำหรับแต่ละกระบวนการ เท่าที่กระบวนการของคุณเกี่ยวข้องคุณมีพื้นที่ที่อยู่ทั้งหมดเพื่อตัวคุณเองและคุณจะได้รับหน่วยความจำ (เสมือน) ที่ต่อเนื่องกันไม่ว่าหน่วยความจำนั้นจะต่อเนื่องกันหรือไม่ก็ตาม

ในความเป็นจริงไม่ว่าหน่วยความจำจะต่อเนื่องกันในหน่วยความจำกายภาพหรือไม่นั้นเป็นสิ่งที่คุณไม่สามารถควบคุมได้ ระบบปฏิบัติการจะเลือกวิธีการจัดสรรบล็อกแบบฟิสิคัลตามที่เห็นสมควรและไม่มีอะไรที่คุณทำในระดับแอปพลิเคชันจะมีผลต่อประโยชน์ (ถ้ามี) ของการมีหน่วยความจำกายภาพที่ต่อเนื่องกัน

คุณจำเป็นต้องใส่ใจเกี่ยวกับการกระจายตัวของหน่วยความจำเสมือนถ้าคุณยังคงจัดสรรและเพิ่มหน่วยความจำขนาดแตกต่างกันเป็นเวลานาน แน่นอนว่ามีความเกี่ยวข้องน้อยกว่ากับพื้นที่ที่อยู่แบบ 64 บิต เกมมักจะไม่ทำงานเป็นเดือนดังนั้นคุณมักจะไม่สนใจเรื่องนี้จนกว่าเราจะพูดถึงเซิร์ฟเวอร์เกมที่ใช้งานมานาน

แม้ว่าคุณจะจัดสรรหน่วยความจำที่มีขนาดแตกต่างกันจำนวนมากในเครื่อง 32 บิตการจัดสรรหน่วยความจำที่ทันสมัยนั้นค่อนข้างดีดังนั้นจึงไม่น่าเป็นไปได้ที่คุณจะได้รับปัญหาการแตกแฟรกเมนต์หน่วยความจำเสมือน

เพื่อซื่อสัตย์กับคุณฉันไม่ทราบว่าสิ่งที่นักเขียนที่เกิดขึ้นเกี่ยวกับ แม้ว่าพื้นที่ที่อยู่จะถูกแชร์และคุณได้บล็อกขนาดใหญ่ที่ต่อเนื่องกันในหน่วยความจำกายภาพโดยการทำให้ว่างคุณกำลังบอกว่าคุณไม่สนใจอีกต่อไป มีโปรแกรมอื่นที่ทำงานบนพื้นหลังที่ทำการจัดสรรของตัวเองดังนั้นแม้ว่า malloc ขนาดใหญ่ของคุณจะประสบความสำเร็จไม่มีใครจะรับประกันได้ว่าโปรแกรมถัดไปจะประสบความสำเร็จเช่นกัน

ฉันคิดว่าเป็นกรณีของ "มันใช้งานได้ด้วยเหตุผลบางอย่างที่ฉันไม่เข้าใจจริงๆดังนั้นฉันจึงตัดสินใจอธิบายบางสิ่ง"


10
RAM ไม่เหมือนฮาร์ดดิสก์ที่หมุนได้ซึ่งมีบล็อกที่ต่อเนื่องกัน "ดีกว่า" ในทางใดทางหนึ่ง นี่ไม่เป็นความจริง. การเข้าถึง RAM ที่ต่อเนื่องเป็นลำดับความสำคัญเร็วกว่าการเข้าถึงแบบสุ่ม ชิปแรมแบ่งออกเป็นส่วน ๆ ซึ่งมีจำนวนเวลาแฝงที่จะเปลี่ยนและที่สำคัญกว่านั้นแคช L1 และ L2 ที่หายไปจะส่งผลกระทบอย่างมากต่อประสิทธิภาพการทำงานของคุณเมื่อหน่วยความจำของคุณกระจัดกระจาย
CaptainCodeman

@CaptainCodeman: ฉันต้องยอมรับว่าออกไปจากความรู้ของฉัน แต่ในทางใดทางหนึ่งในฐานะนักเขียนโปรแกรม Windows คุณไม่สามารถควบคุมได้ว่าหน่วยความจำของคุณต่อเนื่องกันหรือไม่ การขอบล็อกหน่วยความจำขนาดใหญ่จะไม่เปลี่ยนแปลงมากนัก
แพนด้า Pajama

@CaptainCodeman จริง ๆ มีบล็อกเสมือนที่ต่อเนื่องกันอยู่ใน mod ที่ต่อเนื่องกัน 2 ^ N บล็อกใน RAM จะเร็วขึ้นเนื่องจากการจัดสรรสายแคช
วงล้อประหลาด

8
@CaptainCodeman ใช่การเข้าถึง DRAM ตามลำดับนั้นเร็วกว่า แต่เรากำลังพูดถึงการทำแผนที่ทางกายภาพเสมือนที่เกิดขึ้นในหน้า 4 KB (ขึ้นไป) ดังนั้นการทำแผนที่นั้นเป็นลำดับหรือไม่ควรมีผลกระทบต่อหน่วยความจำมากนัก อ่านความเร็ว นอกจากนี้การดึงข้อมูลล่วงหน้าแคชและสิ่งต่างๆเช่นนั้นทำงานในพื้นที่ที่อยู่เสมือนไม่ใช่ทางกายภาพ
นาธานรีด

1
@NathanReed ยุติธรรมเพียงพอและขอขอบคุณสำหรับการชี้แจง ฉันเพิ่งแสดงว่าความเร็วในการเข้าถึง RAM ไม่เหมือนกันทั่วพื้นที่หน่วยความจำตามที่แนะนำ
CaptainCodeman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.