विषय पर बढ़ें

अंतिम अद्यतन:2026-10-12

C++ string SSO परफ़ॉर्मेंस टेस्ट

आज मैं आपसे दो सवाल पूछना चाहता हूँ:

1. नीचे दिए गए कोड में परफ़ॉर्मेंस के लिहाज़ से कोई अंतर है क्या?

std::string s1("hello world hel");
std::string s2("hello world helo");

2. sizeof(std::string) कितना होता है?

चलिए, इन दोनों सवालों का पता लगाते हैं।

चूंकि इन दोनों के उत्तर g++(libstdc++) और clang(libc++) पर अलग-अलग आते हैं, इसलिए यहाँ दोनों का अलग-अलग विश्लेषण किया जाएगा।

1.g++(libstdc++)

g++ के सोर्स कोड का उदाहरण हम g++-10 लेते हैं, पूरा कोड इस github पते पर देखा जा सकता है, यहाँ सबसे मुख्य कोड ही सूचीबद्ध किया गया है।

https://github.com/gcc-mirror/gcc/blob/devel/omp/gcc-10/libstdc%2B%2B-v3/include/bits/basic_string.h#L171

template<typename _CharT, typename _Traits, typename _Alloc>
class basic_string {
  private:
    struct _Alloc_hider : allocator_type {
        pointer _M_p; // The actual data.
    };
      enum { __min_cap = 15 / sizeof(value_type) };
    _Alloc_hider    _M_dataplus;             //  8 bytes
    size_type __size_;                     //  8 bytes

    union {
            _CharT           _M_local_buf[_S_local_capacity + 1]; // 16 bytes 
            size_type        _M_allocated_capacity;                             // 8 bytes
    }; // 16 bytes
}; // 32 bytes

ऊपर दिए गए कोड में कमेंट के हिस्से में string द्वारा घेरे गए बाइट्स की पूरी सूची दी गई है (ध्यान दें: यहाँ value_type की गणना char मानकर की गई है, यानी sizeof(value_type) = 1)।

sizeof(string) = 8 + 8 + 16 = 32।

इसमें 8 बाइट ptr, 8 बाइट size और 16 बाइट का union है।

परफ़ॉर्मेंस के लिहाज़ से, यहाँ SSO लागू किया गया है, लोकल बफ़र में अधिकतम 15 कैरेक्टर तक संग्रहीत होते हैं, और 15 कैरेक्टर से अधिक होने पर heap पर आवंटन हो जाता है, यहाँ मैंने परफ़ॉर्मेंस की तुलना के लिए एक benchmark लिखा है।

  • छोटे स्ट्रिंग की टेस्ट सामग्री: "hello world hel", कुल 15 कैरेक्टर।
  • लंबे स्ट्रिंग की टेस्ट सामग्री: "hello world helo", कुल 16 कैरेक्टर।
std::string s1("hello world hel");
std::string s2("hello world helo");

देखा जा सकता है कि परफ़ॉर्मेंस का अंतर बहुत बड़ा है, केवल एक कैरेक्टर std::string की परफ़ॉर्मेंस में इतना बड़ा अंतर ला देता है!

इसका मूल कारण वही पहले वाला SSO local buffer ही है।

परफ़ॉर्मेंस टेस्ट: https://quick-bench.com/q/s7pvDB_SwQyDCcZk50odAaYIzMc

gcc short long

2.clang++(libc++)

इसी तरह, हम llvm-14 का उदाहरण लेते हैं, पूरा कोड देखना हो तो नीचे दिए github पते पर जाएँ, यहाँ केवल मुख्य कोड निकालकर दिया गया है।

https://github.com/llvm/llvm-project/blob/release/14.x/libcxx/include/string#L765

template<class _CharT, class _Traits, class _Allocator>
class basic_string {
  private:
    struct __long {
        size_type __cap_;               // 8 bytes
        size_type __size_;              // 8 bytes
        pointer   __data_;              // 8 bytes
    };

        enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?
                      (sizeof(__long) - 1)/sizeof(value_type) : 2};

    struct __short {
        union {
            unsigned char __size_;      // 1 bytes
            value_type __lx;            // 1 bytes 
        };                              // 1 bytes
        value_type __data_[__min_cap];  // 23 bytes
    };                                  // 24 bytes

        union __ulx {
            __long __lx;        // 24 bytes
            __short __lxx;  // 24 bytes
        }; // 24 bytes
}

ऊपर दिए गए कोड में कमेंट के हिस्से में string द्वारा घेरे गए बाइट्स की पूरी सूची दी गई है (ध्यान दें: यहाँ value_type की गणना char मानकर की गई है, यानी sizeof(value_type) = 1)।

sizeof(string) = union का आकार, यह union 24 बाइट का है, इसलिए यह 24 के बराबर है।

जबकि SSO में, लोकल बफ़र में 22 से अधिक कैरेक्टर नहीं रहते, 22 कैरेक्टर से अधिक होने पर heap पर आवंटन हो जाता है।

इसलिए जब हम gcc वाला वही टेस्ट कोड clang पर लागू करते हैं, तो हमें काफ़ी अलग परिणाम मिलता है, यानी: long स्ट्रिंग और short स्ट्रिंग की परफ़ॉर्मेंस में ज़्यादा अंतर नहीं है। कारण यह है कि gcc के टेस्ट केस सभी 22 कैरेक्टर के भीतर हैं, यानी सभी छोटे कैरेक्टर ही हैं।

परफ़ॉर्मेंस टेस्ट: https://quick-bench.com/q/nmLMqQZ31cmWBbbIFr2nHN2JL1k

llvm short long no

जब हम वास्तविक लंबे-छोटे स्ट्रिंग टेस्ट करते हैं, तो परफ़ॉर्मेंस में स्पष्ट बदलाव दिखता है, और रुझान gcc के अनुरूप ही रहता है।

  • छोटे स्ट्रिंग की टेस्ट सामग्री: "hello world hello worl", कुल 22 कैरेक्टर।
  • लंबे स्ट्रिंग की टेस्ट सामग्री: "hello world hello world", कुल 23 कैरेक्टर।

परफ़ॉर्मेंस टेस्ट: https://quick-bench.com/q/ujtMrtotEi6RrpfMDJ1UcSLFIJE

llvm short long

संबंधित विषय

टिप्पणियाँ