บทความล่าสุดที่แสดงให้เห็นถึงวิธีการลดการใช้หน่วยความจำของ C struct จาก 96 ไบต์เหลือเพียง 20 ไบต์ ได้ก่อให้เกิดการอภิปรายอย่างมากในหมู่นักพัฒนา โดยเฉพาะอย่างยิ่งเรื่องความถูกต้องทางเทคนิคของคำอธิบายการจัดตำแหน่งและความพร้อมใช้งานของเครื่องมือเฉพาะทางสำหรับการปรับปรุง struct
ผลลัพธ์การปรับปรุงหน่วยความจำ
- ขนาด struct เดิม: 96 ไบต์
- หลังจากจัดเรียงฟิลด์ใหม่: 92 ไบต์ (ลดลง 4 ไบต์)
- หลังจากลบ derived state: 88 ไบต์
- หลังจากใช้ integer types ที่เล็กกว่า: 84 ไบต์
- หลังจากใช้ bitfields: 80 ไบต์
- หลังจากใช้ enum สำหรับชื่อ: 20 ไบต์
- การลดลงทั้งหมด: 76 ไบต์ (เล็กลง 79%)
กฎการจัดตำแหน่งต้องการคำอธิบายที่ชัดเจน
ชุมชนได้เน้นย้ำถึงความไม่ถูกต้องที่สำคัญในการอธิบายการจัดตำแหน่งหน่วยความจำในบทความต้นฉบับ แม้ว่าบทความจะแนะนำว่า CPU ต้องการหน่วยความจำที่จัดตำแหน่งในชุด 4 ไบต์เป็นกฎทั่วไป แต่นักพัฒนาชี้ให้เห็นว่าสิ่งนี้ทำให้ความเป็นจริงง่ายเกินไป ชนิดข้อมูลแต่ละประเภทจริงๆ แล้วมีข้อกำหนดการจัดตำแหน่งเฉพาะของตัวเอง - ตยอางเช่น bool
และ char
มักจะจัดตำแหน่งที่ 1 ไบต์ short
ที่ 2 ไบต์ และ int
ที่ 4 ไบต์ การจัดตำแหน่งโดยรวมของ struct จะกลายเป็นการจัดตำแหน่งสูงสุดของชนิดสมาชิกทั้งหมด ไม่ใช่ข้อกำหนด 4 ไบต์คงที่
ความแตกต่างนี้มีความสำคัญอย่างมากสำหรับนักพัฒนาที่ทำงานบนสถาปัตยกรรมต่างๆ การขยายฟิลด์ int
เป็น long
อาจเพิ่มการจัดตำแหน่งเป็น 8 ไบต์ใน CPU บางตัว ในขณะที่การลบฟิลด์ int
และ float
ทั้งหมดจะลดการจัดตำแหน่งเป็น 1 ไบต์ในระบบส่วนใหญ่
ข้อกำหนดการจัดตำแหน่งของประเภทข้อมูล
bool
/char
: การจัดตำแหน่งแบบ 1 ไบต์short
: การจัดตำแหน่งแบบ 2 ไบต์int
: การจัดตำแหน่งแบบ 4 ไบต์long
: การจัดตำแหน่งแบบ 8 ไบต์ (ใน CPU บางรุ่น)float
: การจัดตำแหน่งแบบ 4 ไบต์- การจัดตำแหน่งของ Struct = การจัดตำแหน่งสูงสุดของประเภทสมาชิก
เครื่องมือระดับมืออาชีพสำหรับการวิเคราะห์ Struct
การอภิปรายเผยให้เห็นว่านักพัฒนาระดับมืออาชีพ โดยเฉพาะผู้ที่ทำงานกับ Linux kernel พึ่งพาเครื่องมือเฉพาะทางมากกว่าการคำนวณด้วยตนเอง เครื่องมือ pahole
จากแพ็กเกจ dwarves โดดเด่นเป็นโซลูชันมาตรฐานที่นักพัฒนา kernel ใช้สำหรับการวิเคราะห์เค้าโครง struct และระบุโอกาสในการปรับปรุง เครื่องมือนี้แสดง padding การจัดตำแหน่ง และแนะนำการปรับปรุงโดยอัตโนมัติ - ซึ่งเป็นข้อได้เปรียบที่สำคัญเหนือวิธีการด้วยตนเองที่อธิบายในบทความต้นฉบับ
สำหรับผู้เริ่มต้นในการเขียนโปรแกรมระบบ การค้นหาเครื่องมือระดับมืออาชีพเหล่านี้อาจเป็นเรื่องท้าทาย เนื่องจากมักไม่มีการจัดทำเอกสารอย่างดีในแหล่งข้อมูลสำหรับผู้เริ่มต้น
การใช้งานที่กว้างขึ้นและคุณสมบัติของภาษาสมัยใหม่
เทคนิคการปรับปรุงที่กล่าวถึงขยายไปเกินกว่าการเขียนโปรแกรม C การพิจารณาเค้าโครงหน่วยความจำที่คล้ายกันนี้ใช้กับภาษาการเขียนโปรแกรมระบบอื่นๆ ทำให้แนวคิดเหล่านี้มีคุณค่าในบริบทการพัฒนาที่แตกต่างกัน
มาตรฐานภาษาสมัยใหม่ยังขยายตัวเลือกสำหรับนักพัฒนา C23 แนะนำ _Float16
สำหรับชนิดจุดทศนิยมที่เล็กกว่า ในขณะที่ C++ เสนอตัวเลือก float16_t
และ bfloat16_t
การเพิ่มเติมเหล่านี้ให้การควบคุมการใช้หน่วยความจำที่ละเอียดมากขึ้น ซึ่งสำคัญโดยเฉพาะสำหรับแอปพลิเคชันที่มีข้อจำกัดหน่วยความจำที่เข้มงวด
การอภิปรายของชุมชนแสดงให้เห็นว่าแม้หลักการปรับปรุงหลักจะยังคงมีคุณค่า แต่นักพัฒนาได้ประโยชน์จากการเข้าใจทั้งทฤษฎีพื้นฐานและเครื่องมือระดับมืออาชีพที่มีอยู่เพื่อนำแนวคิดเหล่านี้ไปใช้อย่างมีประสิทธิภาพในโครงการจริง
อ้างอิง: Writing memory efficient C structs