अंतिम अद्यतन:2026-10-12
C++ string SSO परफ़ॉर्मेंस टेस्ट¶
आज मैं आपसे दो सवाल पूछना चाहता हूँ:
1. नीचे दिए गए कोड में परफ़ॉर्मेंस के लिहाज़ से कोई अंतर है क्या?
2. sizeof(std::string) कितना होता है?
चलिए, इन दोनों सवालों का पता लगाते हैं।
चूंकि इन दोनों के उत्तर g++(libstdc++) और clang(libc++) पर अलग-अलग आते हैं, इसलिए यहाँ दोनों का अलग-अलग विश्लेषण किया जाएगा।
1.g++(libstdc++)¶
g++ के सोर्स कोड का उदाहरण हम g++-10 लेते हैं, पूरा कोड इस github पते पर देखा जा सकता है, यहाँ सबसे मुख्य कोड ही सूचीबद्ध किया गया है।
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 की परफ़ॉर्मेंस में इतना बड़ा अंतर ला देता है!
इसका मूल कारण वही पहले वाला SSO local buffer ही है।
परफ़ॉर्मेंस टेस्ट: https://quick-bench.com/q/s7pvDB_SwQyDCcZk50odAaYIzMc

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

जब हम वास्तविक लंबे-छोटे स्ट्रिंग टेस्ट करते हैं, तो परफ़ॉर्मेंस में स्पष्ट बदलाव दिखता है, और रुझान gcc के अनुरूप ही रहता है।
- छोटे स्ट्रिंग की टेस्ट सामग्री: "hello world hello worl", कुल 22 कैरेक्टर।
- लंबे स्ट्रिंग की टेस्ट सामग्री: "hello world hello world", कुल 23 कैरेक्टर।
परफ़ॉर्मेंस टेस्ट: https://quick-bench.com/q/ujtMrtotEi6RrpfMDJ1UcSLFIJE

संबंधित विषय¶
- memcpy और std::copy परफ़ॉर्मेंस तुलना | C++那些事
- C++ पॉलीमॉर्फ़िज़्म: वर्चुअल फ़ंक्शन, CRTP और variant | C++那些事