Hacker News

เหตุใดการจัดสรร C ++ (m) แรกจึงเป็น 72 KB เสมอ

ค้นหาว่าเหตุใดการจัดสรรหน่วยความจำ C++ ครั้งแรกของคุณจึงขอ 72 KB แทนที่จะเป็นไบต์ที่คาดไว้ สำรวจคำอธิบายเกี่ยวกับชั้นการจัดการหน่วยความจำภายในและชั้นการจัดการหน่วยความจำ OS ของ malloc

1 นาทีอ่าน

Mewayz Team

Editorial Team

Hacker News

ความลึกลับเบื้องหลังการจัดสรร C++ ครั้งแรกของคุณ

คุณเขียนโปรแกรม C++ อย่างง่าย int ใหม่อันเดียว สี่ไบต์ คุณเริ่ม strace หรือผู้สร้างโปรไฟล์หน่วยความจำที่คุณชื่นชอบ และนั่นก็เป็นเช่นนั้น — กระบวนการของคุณเพิ่งร้องขอประมาณ 72 KB จากระบบปฏิบัติการ ไม่ใช่ 4 ไบต์ ไม่ใช่ 64 ไบต์ เต็ม 72 KB. หากคุณเคยจ้องมองตัวเลขนั้นและสงสัยว่าเครื่องมือของคุณโกหกคุณหรือไม่ แสดงว่าคุณไม่ได้อยู่คนเดียว พฤติกรรมที่ดูเหมือนจะแปลกประหลาดนี้เป็นหนึ่งในคำถามที่พบบ่อยที่สุดในหมู่นักพัฒนา C++ ที่เจาะลึกหน่วยความจำภายในเป็นครั้งแรก และคำตอบจะนำเราไปสู่การเดินทางอันน่าทึ่งผ่านเลเยอร์ที่อยู่ระหว่างโค้ดของคุณกับฮาร์ดแวร์จริง

จะเกิดอะไรขึ้นเมื่อคุณโทรหาใหม่

เพื่อให้เข้าใจตัวเลขขนาด 72 KB คุณต้องติดตามห่วงโซ่การจัดสรรทั้งหมด เมื่อโค้ด C++ ของคุณรัน int ใหม่ คอมไพลเลอร์จะแปลสิ่งนั้นเป็นการเรียกไปยังโอเปอเรเตอร์ new ซึ่งในระบบ Linux ส่วนใหญ่จะมอบหมายให้กับ malloc จาก glibc แต่ malloc ไม่ได้ถามเคอร์เนลโดยตรงถึงหน่วยความจำ 4 ไบต์ เคอร์เนลทำงานในเพจต่างๆ — โดยทั่วไปมีขนาด 4 KB บน x86_64 — และค่าใช้จ่ายในการเรียกระบบนั้นสูงมากเมื่อเทียบกับการเข้าถึงหน่วยความจำแบบธรรมดา การเรียก brk() หรือ mmap() สำหรับการจัดสรรแต่ละครั้งจะทำให้โปรแกรมที่ไม่สำคัญใดๆ หยุดชะงักลง

แต่ตัวจัดสรรหน่วยความจำของ glibc ซึ่งเป็นการดำเนินการที่เรียกว่า ptmalloc2 ซึ่งสืบเชื้อสายมาจาก dlmalloc แบบคลาสสิกของ Doug Lea ทำหน้าที่เป็นคนกลางแทน โดยจะขอบล็อกหน่วยความจำขนาดใหญ่จากเคอร์เนลล่วงหน้า จากนั้นจึงแยกออกเป็นชิ้นเล็กๆ ตามที่โปรแกรมของคุณต้องการ นี่เป็นเหตุผลพื้นฐานที่การจัดสรร 4 ไบต์แรกของคุณทำให้เกิดการร้องขอที่ใหญ่กว่ามากไปยังระบบปฏิบัติการ ผู้จัดสรรไม่สิ้นเปลือง มันเป็นกลยุทธ์

การแยกส่วน 72 KB: ไบต์ไปอยู่ที่ไหน

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

ขั้นแรก malloc ของ glibc เริ่มต้นเวทีหลัก — โครงสร้างการบัญชีหลักที่ติดตามการจัดสรรทั้งหมดบนเธรดหลัก เวทีนี้มีข้อมูลเมตาสำหรับฮีป ตัวชี้รายการอิสระ และโครงสร้างถังสำหรับขนาดการจัดสรรที่แตกต่างกัน ตัวจัดสรรจะขยายการแตกโปรแกรมผ่าน sbrk() และส่วนขยายเริ่มต้นจะถูกควบคุมโดยพารามิเตอร์ภายในที่เรียกว่า M_TOP_PAD ซึ่งมีค่าเริ่มต้นอยู่ที่ 128 KB ของช่องว่างภายใน อย่างไรก็ตาม คำขอเริ่มต้นจริงจะได้รับการปรับเปลี่ยนสำหรับการจัดแนวหน้าและตำแหน่งตัวแบ่งที่มีอยู่ ซึ่งมักจะส่งผลให้คำขอแรกมีขนาดเล็กลง ซึ่งโดยทั่วไปจะเชื่อมโยงไปถึงใกล้กับตัวเลข 72 KB ในกระบวนการที่เริ่มต้นใหม่

💡 คุณรู้หรือไม่?

Mewayz ทดแทนเครื่องมือธุรกิจ 8+ รายการในแพลตฟอร์มเดียว

CRM · การออกใบแจ้งหนี้ · HR · โปรเจกต์ · การจอง · อีคอมเมิร์ซ · POS · การวิเคราะห์ แผนฟรีใช้ได้ตลอดไป

เริ่มฟรี →

ประการที่สอง ตั้งแต่ glibc 2.26 ตัวจัดสรรจะเตรียมใช้งานแคชภายในเธรด (tcache) ในการใช้งานครั้งแรก tcache มี 64 bins (หนึ่งอันต่อคลาสขนาดการจัดสรรขนาดเล็ก) แต่ละอันสามารถเก็บแคชได้สูงสุด 7 ชิ้น tcache_perthread_struct เองกินพื้นที่ประมาณ 1 KB แต่การดำเนินการในการเริ่มต้นจะทำให้เกิดการตั้งค่าพื้นที่ที่กว้างขึ้น ประการที่สาม รันไทม์ C++ ได้ดำเนินการจัดสรรก่อนที่ main() ของคุณจะรันด้วยซ้ำ — ตัวสร้างแบบสแตติก การเริ่มต้นบัฟเฟอร์ iostream สำหรับ std::cout และเพื่อน และการตั้งค่าโลแคล ล้วนมีส่วนทำให้เกิดฮีปเริ่มต้นนั้น

ระบบอารีน่าและเหตุใดการจัดสรรล่วงหน้าจึงชาญฉลาด

การตัดสินใจจัดสรรหน่วยความจำจำนวนมากล่วงหน้า แทนที่จะขอให้แบ่งส่วนนั้นไม่ใช่อุบัติเหตุของการดำเนินการ มันเป็นการแลกเปลี่ยนทางวิศวกรรมโดยเจตนาซึ่งมีรากฐานมาจากประสบการณ์การเขียนโปรแกรมระบบหลายทศวรรษ การเรียกใช้ brk() หรือ mmap() ทุกครั้งเกี่ยวข้องกับการสลับบริบทจากพื้นที่ผู้ใช้ไปเป็นพื้นที่เคอร์เนล การปรับเปลี่ยนการแมปหน่วยความจำเสมือนของกระบวนการ และการอัพเดตตารางเพจที่เป็นไปได้ สำหรับฮาร์ดแวร์สมัยใหม่ การเรียกระบบเพียงครั้งเดียวมีค่าใช้จ่ายประมาณ 100-200 นาโนวินาที ซึ่งถือว่าน้อยมากหากแยกออกจากกัน และถือเป็นหายนะในวงกว้าง

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

Build Your Business OS Today

From freelancers to agencies, Mewayz powers 138,000+ businesses with 207 integrated modules. Start free, upgrade when you grow.

Create Free Account →

Frequently Asked Questions

ทำไมต้อง 72 KB ด้วยล่ะ? ทำไมไม่ใช่จำนวนที่น้อยกว่า?

72 KB เป็นผลมาจากกลไก "พื้นที่สำรอง" หรือ "memory arena" ที่ตัวจัดการหน่วยความจำของ C++ runtime สร้างขึ้นในครั้งแรก เป้าหมายหลักไม่ใช่เพื่อจัดสรรตัวแปรของคุณโดยตรง แต่เพื่อสร้างพูลหน่วยความจำเริ่มต้นสำหรับการจัดสรรขนาดเล็กในอนาคต ซึ่งช่วยลดจำนวนการเรียกระบบที่ใช้ทรัพยากรสูง (system calls) ไปยังเคอร์เนลของระบบปฏิบัติการ เหมือนกับการซื้อของทีละมากๆ เพื่อประหยัดเวลาในการเดินทางหลายรอบ

แล้วถ้าผมใช้ไลบรารีอื่น เช่น tcmalloc หรือ jemalloc ล่ะ?

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

หน่วยความจำ 72 KB นี้ถูกใช้ไปทำอะไรบ้าง?

พื้นที่ 72 KB นี้ไม่ได้ถูกใช้เพื่อเก็บข้อมูลของโปรแกรมคุณเพียงอย่างเดียว แต่ถูกแบ่งออกเป็นส่วนๆ สำหรับโครงสร้างการจัดการภายในของตัวรันไทม์ C++ ซึ่งรวมถึงข้อมูลสำหรับติดตามการจัดสรรและยกเลิกการจัดสรร บางส่วนอาจถูกสำรองไว้สำหรับ "เฮป" (heap) ขนาดเล็ก และบางส่วนอาจถูกใช้โดยโครงสร้างข้อมูลเริ่มต้นของตัวรันไทม์ เช่น ตัวจัดการข้อยกเว้นหรือสตรีมมาตรฐาน บางส่วนยังคงว่างไว้สำหรับการจองในอนาคต

มีวิธีหลีกเลี่ยงไม่ให้จองหน่วยความจำมากขนาดนี้ตั้งแต่แรกไหม?

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

ลองใช้ Mewayz ฟรี

แพลตฟอร์มแบบออล-อิน-วันสำหรับ CRM, การออกใบแจ้งหนี้, โครงการ, HR และอื่นๆ ไม่ต้องใช้บัตรเครดิต

เริ่มจัดการธุรกิจของคุณอย่างชาญฉลาดวันนี้

เข้าร่วมธุรกิจ 30,000+ ราย แผนฟรีตลอดไป · ไม่ต้องใช้บัตรเครดิต

พบว่าสิ่งนี้มีประโยชน์หรือไม่? แบ่งปันมัน

พร้อมนำไปปฏิบัติแล้วหรือยัง?

เข้าร่วมธุรกิจ 30,000+ รายที่ใช้ Mewayz แผนฟรีตลอดไป — ไม่ต้องใช้บัตรเครดิต

เริ่มต้นทดลองใช้ฟรี →

พร้อมที่จะลงมือทำหรือยัง?

เริ่มต้นทดลองใช้ Mewayz ฟรีวันนี้

แพลตฟอร์มธุรกิจแบบครบวงจร ไม่ต้องใช้บัตรเครดิต

เริ่มฟรี →

ทดลองใช้ฟรี 14 วัน · ไม่ต้องใช้บัตรเครดิต · ยกเลิกได้ทุกเมื่อ