ความเป็นมา / ภาพรวม
การดำเนินการกับตัวแปรอัตโนมัติ ("จากสแต็ก" ซึ่งเป็นตัวแปรที่คุณสร้างโดยไม่ต้องโทรmalloc
/ new
) โดยทั่วไปเร็วกว่าที่เกี่ยวข้องกับร้านค้าฟรี ("ฮีป" ซึ่งเป็นตัวแปรที่สร้างขึ้นโดยใช้new
) อย่างไรก็ตามขนาดของอาร์เรย์อัตโนมัติจะถูกกำหนดไว้ที่เวลาคอมไพล์ แต่ขนาดของอาร์เรย์จากร้านค้าฟรีนั้นไม่ใช่ ยิ่งไปกว่านั้นขนาดสแต็กมี จำกัด (โดยทั่วไปจะเป็นเพียงไม่กี่ MiB) ในขณะที่ร้านค้าฟรีจะถูก จำกัด ด้วยหน่วยความจำของระบบของคุณเท่านั้น
SSO คือการเพิ่มประสิทธิภาพสตริงสั้น / ขนาดเล็ก std::string
มักจะเก็บสตริงเป็นตัวชี้ไปยังร้านค้าฟรี ( "กอง") new char [size]
ซึ่งจะช่วยให้ลักษณะการทำงานที่คล้ายกันเช่นถ้าคุณมีการโทร สิ่งนี้จะป้องกันการโอเวอร์โฟลว์ของสแต็กสำหรับสตริงที่มีขนาดใหญ่มาก แต่อาจช้าลงโดยเฉพาะอย่างยิ่งกับการคัดลอก การเพิ่มประสิทธิภาพการใช้งานหลายสร้างอาร์เรย์อัตโนมัติขนาดเล็กบางอย่างเช่นstd::string
char [20]
หากคุณมีสตริงที่มี 20 ตัวอักษรหรือเล็กกว่า (ตามตัวอย่างนี้ขนาดจริงจะแตกต่างกันไป) มันจะเก็บมันไว้ในอาร์เรย์นั้นโดยตรง วิธีนี้จะช่วยหลีกเลี่ยงความต้องการในการโทรnew
เลยซึ่งจะช่วยเพิ่มความเร็ว
แก้ไข:
ฉันไม่ได้คาดหวังว่าคำตอบนี้จะได้รับความนิยมอย่างมาก แต่เนื่องจากเป็นเช่นนั้นฉันขอให้มีการนำไปใช้จริงมากขึ้นด้วยข้อแม้ที่ฉันไม่เคยอ่านการใช้งาน SSO "ในป่า"
รายละเอียดการใช้งาน
อย่างน้อยที่สุดstd::string
ความต้องการในการจัดเก็บข้อมูลต่อไปนี้:
- ขนาด
- ความจุ
- ตำแหน่งของข้อมูล
ขนาดสามารถจัดเก็บเป็นstd::string::size_type
หรือเป็นตัวชี้ไปยังจุดสิ้นสุด ความแตกต่างเพียงอย่างเดียวคือไม่ว่าคุณจะต้องการให้มีการลบสองตัวชี้เมื่อโทรของผู้ใช้size
หรือเพิ่มตัวชี้เมื่อโทรของผู้ใช้size_type
end
ความจุสามารถจัดเก็บได้ทั้งสองทางเช่นกัน
คุณไม่ต้องจ่ายเงินสำหรับสิ่งที่คุณไม่ได้ใช้
ก่อนอื่นให้พิจารณาการนำไปปฏิบัติที่ไร้เดียงสาตามสิ่งที่ฉันระบุไว้ข้างต้น:
class string {
public:
// all 83 member functions
private:
std::unique_ptr<char[]> m_data;
size_type m_size;
size_type m_capacity;
std::array<char, 16> m_sso;
};
สำหรับระบบ 64 บิตซึ่งโดยทั่วไปหมายความว่าstd::string
มี 24 ไบต์ของ 'ค่าใช้จ่าย' ต่อสตริงและอีก 16 สำหรับบัฟเฟอร์ SSO (16 เลือกที่นี่แทนที่จะเป็น 20 เนื่องจากข้อกำหนดด้านการขยาย) มันไม่สมเหตุสมผลเลยที่จะจัดเก็บข้อมูลสมาชิกทั้งสามเหล่านั้นรวมทั้งอาเรย์ของตัวละครในท้องถิ่นเช่นในตัวอย่างที่เรียบง่ายของฉัน ถ้าm_size <= 16
ฉันจะใส่ข้อมูลทั้งหมดลงm_sso
ไปฉันก็รู้แล้วว่าความจุและฉันไม่ต้องการตัวชี้ไปยังข้อมูล หากแล้วฉันไม่จำเป็นต้องm_size > 16
m_sso
ไม่มีการทับซ้อนอย่างที่ฉันต้องการทั้งหมด โซลูชันที่ชาญฉลาดกว่าที่ไม่มีที่ว่างจะมีลักษณะคล้ายนี้เล็กน้อย (วัตถุประสงค์ที่ยังไม่ทดลองตัวอย่างเท่านั้น):
class string {
public:
// all 83 member functions
private:
size_type m_size;
union {
class {
// This is probably better designed as an array-like class
std::unique_ptr<char[]> m_data;
size_type m_capacity;
} m_large;
std::array<char, sizeof(m_large)> m_small;
};
};
ฉันคิดว่าการใช้งานส่วนใหญ่มีลักษณะเช่นนี้
std::string
ดำเนินการ" และอีกถามว่า "สิ่งที่ไม่ SSO หมายความว่า" คุณจะต้องเป็นอย่างบ้าที่จะต้องพิจารณาพวกเขาจะเหมือนกันคำถาม