Shared_ptr और C ++ 11 का प्रदर्शन: मैं पुस्तकालयों को क्यों नहीं मानता

आपका स्वागत है!

मैंने एक बार कोड के एक महत्वपूर्ण खंड को अनुकूलित कर लिया था, और वहां बढ़ावा दिया गया था :: share_ptr ... और मुझे एहसास हुआ: मैं पुस्तकालयों पर विश्वास नहीं करता, हालांकि स्मार्ट चाचा उन्हें लिखते हैं।

कट के तहत विवरण।

इसलिए, मैंने कोड को अनुकूलित किया, और ऐसा एक खंड था:
ऑटो pRes = बढ़ावा :: static_pointer_cast < TBase > ( बढ़ावा :: आवंटित_शेयर < TDerived > ( TAllocator ( ) ) ) ;
// ... पी के साथ कुछ कर रहा है
वापसी std :: चाल ( pRes )

अनुकूलन समाप्त हो रहा था, इसलिए रिलीज़ को संकलित किया गया था, और मैंने डिससमैबलर में देखने का फैसला किया कि मेरे पसंदीदा स्टूडियो ने मेरे लिए क्या संकलित किया है, जिससे कुछ सुंदर और तेज़ देखने की उम्मीद है। बस यही मैंने देखा तो चौंक गया:
; -------------------------------------------------- -------------------------------------------
; लाइन 76: ऑटो pRes = बढ़ावा :: static_pointer_cast <CBase> (बढ़ावा :: make_sared <CDerived> ());

; ... कुछ भी दिलचस्प नहीं - पैरामीटर तैयार करें
कॉल बूस्ट :: मेक_शेयर <CDerived> ( 0D211D0h )
; ... फिर से कुछ भी दिलचस्प नहीं है - पैरामीटर तैयार करें
कॉल बूस्ट :: static_pointer_cast <CBase , CDerived> ( 0D212F0h )
; ... फिर से, कुछ भी दिलचस्प नहीं - एक कॉल परिणाम प्राप्त करना

; ऐसा लगता है कि अगर (pRes) चेक, वास्तव में यह कोई फर्क नहीं पड़ता। यह महत्वपूर्ण है कि जेई बहिष्कृत नहीं है
टेस्ट ईएक्स , ईएक्सएक्स
je `अनाम नामस्थान` :: f + 7Ah ( 0D210CAh ) ; -> हम कहीं भी नहीं कूदते, हमारे पास pRes! = 0 है
; ... कुछ भी दिलचस्प नहीं है

; एपिक फेल # 1 - इंटरलॉक्ड सीएमपी एक्सचेंज
; यह ब्लॉक वास्तव में एक परिणाम के रूप में बनाए गए अस्थायी साझा_प्ट्र को निकालता है
; make_sared कॉल: यहां वे संदर्भ संख्या को कम करते हैं और फिर एक सशर्त छलांग लगाते हैं,
; यदि संदर्भ गणना शून्य नहीं है (जो, जाहिर है, हमारा विकल्प है,
; क्योंकि हम एक पॉइंटर बना रहे हैं)।
xadd dword ptr [ eax ] , ecx को लॉक करें
jne `अनाम नामस्थान` :: f + 7Ah ( 0D210CAh ) ; -> c ++ कोड में अगली लाइन पर जाएं

; ... वहाँ अभी भी एक संभावित सूचक विलोपन है, लेकिन यह मृत कोड है

; -------------------------------------------------- -------------------------------------------
; पंक्ति 78: वापसी एसटीडी :: चाल (pRes);

; असेंबलर, मैं शायद थक गया।
; इस ब्लॉक में, एपिक फेल # 2 - इंटरलॉक्ड इंक्रीमेंट को सबसे पहले कहा जाता है, क्योंकि हम नकल करते हैं
; मान वापस करने के लिए pRes। फिर एपिक फेल # 3 - रिजल्ट के रूप में इंटरलैंप सीएमपी एक्सचेंज
; PRes सूचक का विलोपन (मेमोरी स्वाभाविक रूप से मुक्त नहीं होती है)

मुझे लगता है कि मैंने Make_sared और static_pointer_cast कॉल के अंदर 3 और इंटरलॉक किए गए निर्देशों के बारे में उल्लेख नहीं किया है ... मैंने इसे देखा और अपनी आंखों के सामने खराब होने लगा। ऐसा क्या है जो निकला? मैं यहाँ विशेष रूप से मूव कन्स्ट्रक्टर्स का आह्वान कर रहा हूँ, लेकिन उन्होंने मुझे संदर्भ संख्या आगे और पीछे घुमाई?

* गीतात्मक विषयांतर: इतना बुरा क्या है।
मुझे लगता है कि हर कोई जानता है कि एक स्मार्ट पॉइंटर share_ptr नामक चीज ने इसके अंदर एक पॉइंटर को साझा किए गए पॉइंटर्स की संख्या के लिए रखा है जो एक ही संग्रहीत ऑब्जेक्ट को संदर्भित करता है। जब हम share_ptr को कॉपी करते हैं, तो यह बहुत अधिक मात्रा में बढ़ जाता है, और जब हम इसे नष्ट करते हैं, तो यह घट जाता है। अंतिम साझा सूचक के विनाश के दौरान, लिंक की संख्या शून्य हो जाती है और संग्रहीत वस्तु को इसके साथ हटा दिया जाता है। तो, इसके लिए एक बहु-थ्रेडेड वातावरण में ठीक काम करने के लिए, आपको परमाणु परिचालनों के साथ लिंक की संख्या को बदलने की आवश्यकता है, कोडांतरक लॉक उपसर्ग के साथ बहुत ही: यह उपसर्ग सुनिश्चित करता है कि प्रोसेसर बिल्कुल सही काम करता है, और कोई भी कैश हमें जीने से नहीं रोकेगा। उपसर्ग अच्छा है, केवल धीमा है, बहुत धीमा है। यह परिमाण के लगभग 2 आदेशों द्वारा टीम को धीमा कर देता है, क्योंकि एक कैश लाइन रीसेट की आवश्यकता है, जिसका अर्थ है कि आपको इसे यथासंभव कम उपयोग करने की आवश्यकता है।

* लयात्मक विषयांतर 2: यह कैसे हुआ और क्यों कोई परमाणु निर्देश नहीं होना चाहिए।
C ++ 11 ने हमें एक बहुत स्वादिष्ट चीज़ दी, जिसे मूव शब्दार्थ कहा जाता है। अब आप "मूविंग" कंस्ट्रक्टर्स को परिभाषित कर सकते हैं, जो इसकी एक प्रति बनाने के बजाय एक ऑब्जेक्ट से दूसरे ऑब्जेक्ट पर डेटा ले जाते हैं। इस तरह के एक निर्माणकर्ता, उदाहरण के लिए, एक सूचक को आंतरिक स्ट्रिंग बफ़र से एक std :: string से दूसरे में ले जाता है, जिससे आपको बिना रिक्लाइन मेमोरी के एक ऑब्जेक्ट से दूसरी वस्तु को स्थानांतरित करने की अनुमति मिलती है। उसी तरह, यह संभव है (और आवश्यक!) संदर्भ काउंटर को एक से साझा करने के लिए दूसरे से स्थानांतरित करने के लिए। दरअसल, इस मामले में, हमें किसी भी परमाणु संचालन की आवश्यकता नहीं है, क्योंकि हम संकेत की संख्या को नहीं बदलते हैं। हम सिर्फ एक से दूसरे में सभी आंतरिक डेटा "ट्रांसफर" करते हैं (जबकि सूचक जिसमें से हमने डेटा लिया था वह कहीं भी इंगित नहीं करता है)।

तो यह कैसे हुआ ... शायद अनदेखी हुई। मैं एक आंसू पत्र को बढ़ावा देने के लिए लिखना चाहता था, मैंने भी इसे करना शुरू कर दिया ... लेकिन फिर मुझे कुछ मिला जिसने मुझे पूरी तरह से मारा। बढ़ावा देने के निर्माण के दौरान :: share_ptr, get_deleter फ़ंक्शन टाइपिड (ओह देवताओं!) के माध्यम से तुलना करता है। मुझे नहीं पता कि उनके पास यह कैसे है, लेकिन मेरा कंपाइलर स्ट्रैम्प (दुख की बात है, यह नहीं है?) के माध्यम से करता है।

फिर मैंने बूस्ट की तुलना में मानक पुस्तकालय की गति को मापने का फैसला किया। 2 बार! बढ़ावा देना :: make_sared std की तुलना में 2 गुना धीमा है :: make_sared! क्यों, आप पूछें? यह सरल है, बूस्ट 2 ऑब्जेक्ट्स के लिए मेमोरी आवंटित करता है - एक संदर्भ काउंटर और वास्तव में संग्रहीत ऑब्जेक्ट। लेकिन मानक पुस्तकालय - केवल एक के लिए, इस ऑब्जेक्ट में दोनों शामिल हैं। और स्मृति का आवंटन - यह धीमा है। ओरल प्लस Microsoft के पास गया, एक और वहां गया क्योंकि स्मार्ट पॉइंटर्स मानक पुस्तकालय में काम करते हैं - चाल निर्माणकर्ता कोई भी परमाणु संचालन नहीं करता है। पॉइंटर बनाना लॉक फ्री मोड में होता है ... खैर, लगभग। उन्होंने static_pointer_cast को मास्टर नहीं किया: यह पॉइंटर को कॉपी करता है चाहे वह कोई भी चीज ले जाए। यह समस्या "डोपिलिवैनी" पुस्तकालय द्वारा हल की गई थी। दूसरे प्लेटफ़ॉर्म पर पोर्टेबल नहीं है, लेकिन मानक के अनुकूल है, आप इसे यहाँ डाउनलोड कर सकते हैं: pastebin.com/XZaE2cnW - MSVC2010 में काम करता है।

पुनश्च

इसलिए हमारा आज का विजेता MSVC2010 से अलग है: इसमें कुल मिलाकर एक प्लस है
लेकिन बढ़ावा अशुभ था: -1

खैर, मैं अलविदा कहता हूं, मुझे उम्मीद है कि कम से कम यह जानकारी किसी के लिए उपयोगी थी। एसटीडी :: share_ptr का उपयोग करें, मेमोरी को मेक / आवंटन के माध्यम से आवंटित करें और खुश रहें :)

Source: https://habr.com/ru/post/In138658/


All Articles