c++ - معنى اختصار SSO في سياق std:: string




optimization (2)

الخلفية / نظرة عامة

تكون العمليات على المتغيرات التلقائية ("من المكدس" ، وهي متغيرات تقوم بإنشائها دون استدعاء 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 بايت من 'overhead' لكل سلسلة ، بالإضافة إلى 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;
    };
};

أفترض أن معظم التطبيقات تبدو أكثر مثل هذا.

في سؤال C ++ حول التحسين ونمط التعليمات البرمجية ، أشار العديد من الإجابات إلى "SSO" في سياق تحسين نسخ std::string . ماذا يعني SSO في هذا السياق؟

بوضوح لا "تسجيل الدخول الفردي". "تحسين السلسلة المشتركة" ، ربما؟


SSO هو اختصار لـ "Small String Optimization" ، وهي تقنية يتم فيها تضمين سلاسل صغيرة في نص فئة السلسلة بدلاً من استخدام مخزن مؤقت مخصص بشكل منفصل.





optimization