2009-05-12 7 views
21

मैं एक बहु थ्रेडेड अनुप्रयोग डीबग कर रहा था और CRITICAL_SECTION की आंतरिक संरचना पाई। मुझे CRITICAL_SECTION के डेटा सदस्य LockSemaphore को एक दिलचस्प व्यक्ति मिला।क्या गंभीर अनुभाग हमेशा तेज है?

ऐसा लगता है कि LockSemaphore एक ऑटो-रीसेट ईवेंट है (नाम के रूप में एक सेमफोर नहीं है) और ऑपरेटिंग सिस्टम चुपचाप इस घटना को बनाता है जब पहली बार थ्रेड Critcal Section पर प्रतीक्षा करता है जो किसी अन्य थ्रेड द्वारा लॉक किया जाता है।

अब, मुझे आश्चर्य है कि गंभीर अनुभाग हमेशा तेज है? इवेंट एक कर्नेल ऑब्जेक्ट है और प्रत्येक क्रिटिकल सेक्शन ऑब्जेक्ट इवेंट ऑब्जेक्ट से जुड़ा हुआ है, तो Critical Section म्यूटेक्स जैसी अन्य कर्नेल ऑब्जेक्ट्स की तुलना में तेज़ी से कैसे हो सकता है? साथ ही, आंतरिक घटना वस्तु वास्तव में गंभीर खंड के प्रदर्शन को कैसे प्रभावित करती है?

struct RTL_CRITICAL_SECTION 
{ 
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 
    LONG LockCount; 
    LONG RecursionCount; 
    HANDLE OwningThread; 
    HANDLE LockSemaphore; 
    ULONG_PTR SpinCount; 
}; 
+2

यह भी याद रखें कि क्रिटिकलसेक्शन कार्यान्वयन विवरण ओएस के संस्करण से संस्करण में भिन्न हो सकते हैं। इन विवरणों को देखने के लिए निर्देशक हो सकते हैं, लेकिन उन पर भरोसा न करें, क्योंकि वे बदल सकते हैं। –

+0

यह निश्चित रूप से NT5 – paulm

उत्तर

34

जब वे कहते हैं कि एक महत्वपूर्ण खंड "तेज़" है, तो उनका मतलब है "यह किसी अन्य थ्रेड द्वारा पहले से लॉक नहीं होने पर एक अधिग्रहण करना सस्ता है"।

[ध्यान दें कि अगर यह पहले से ही एक और धागा द्वारा बंद कर दिया है, तो यह बात लगभग इतना है कि यह कैसे तेज है नहीं करता है।]

कारण है कि यह तेजी से है, क्योंकि, कर्नेल में जाने से पहले , यह उन LONG फ़ील्ड (शायद LockCount फ़ील्ड पर) पर InterlockedIncrement के समतुल्य का उपयोग करता है (यदि LockCount फ़ील्ड पर) और यदि यह सफल होता है तो यह कर्नेल में घुसने के बिना लॉक को एक्वार्ड किया जाता है।

InterlockedIncrement एपीआई मुझे लगता है कि उपयोगकर्ता मोड में "लॉक इंक" ओपोड के रूप में लागू किया गया है ... दूसरे शब्दों में आप कर्नेल में किसी भी अंगूठी संक्रमण के बिना एक अनचाहे महत्वपूर्ण अनुभाग प्राप्त कर सकते हैं।

+1

+1 अच्छा स्पष्टीकरण। यदि आप लॉककाउंट पढ़कर महत्वपूर्ण अनुभाग प्राप्त कर सकते हैं तो प्रभावी ढंग से आप स्वयं का परीक्षण कर सकते हैं। – Arno

+0

@ अरनो: इसके लिए ['tryEnterCriticalSection'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686857%28v=vs.85%29.aspx) है। – rwong

3

CriticalSections कुछ समय (कुछ एमएस) स्पिन और जाँच अगर ताला नि: शुल्क है रखेंगे:

यहाँ CRITICAL_SECTION की संरचना है। स्पिन गिनती के बाद 'टाइम्स आउट' के बाद, यह कर्नेल घटना पर वापस आ जाएगा। तो ऐसे मामले में जहां लॉक धारक जल्दी से बाहर हो जाता है, आपको कर्नेल कोड में महंगी संक्रमण कभी नहीं करना पड़ता है।

संपादित करें: चला गया और मेरे कोड में कुछ टिप्पणी नहीं मिली: जाहिरा तौर पर एमएस ढेर प्रबंधक 4000 की एक स्पिन गिनती (पूर्णांक वेतन वृद्धि, नहीं एमएस)

+1

में एक सेमफोर है 4 सेकंड थोड़ा अधिक नहीं है? साथ ही, इवेंट ऑब्जेक्ट को पल बनाया जाता है जब ओएस को महत्वपूर्ण खंड लॉक हो जाता है। यह थोड़ा ऊपर है, है ना? –

+0

वाह, कंप्यूटर शर्तों में 4 सेकंड बड़ा है ... क्या आप शायद 4000 माइक्रोसेकंड (यानी 4ms) का मतलब है? मुझे नहीं लगता कि एक संदर्भ स्विच आधुनिक मशीन पर 4 एमएमएस भी लेता है। क्या आप 4sec आकृति का उद्धरण प्रदान कर सकते हैं? – rmeador

+4

असल में, स्पिन गिनती मान सिर्फ एक गिनती है - यह समय की इकाइयों में व्यक्त मूल्य नहीं है। 4,000 मान एमएसडीएन दस्तावेज से प्रारंभिक क्रिटिकलसेक्शन एंडस्पिनकाउंट() के लिए आता है नोट करें कि यह रिलीज से रिलीज में बदल सकता है। दस्तावेज़ 'लगभग 4,000' कहते हैं। – Foredecker

25

प्रदर्शन काम में, कुछ बातें "हमेशा" श्रेणी में आते हैं का उपयोग करता है :) यदि आप स्वयं को कुछ लागू करते हैं जो कि अन्य प्राइमेटिव्स का उपयोग करते हुए एक ओएस महत्वपूर्ण खंड के समान है तो बाधाएं ज्यादातर मामलों में धीमी हो जाएंगी।

प्रदर्शन प्रश्न के साथ आपके प्रश्न का उत्तर देने का सबसे अच्छा तरीका है। ओएस ऑब्जेक्ट्स कैसे प्रदर्शन करते हैं बहुत परिदृश्य पर निर्भर करता है। उदाहरण के लिए, यदि विवाद कम है तो महत्वपूर्ण वर्गों को आम तौर पर 'तेज़' माना जाता है। यदि लॉक टाइम स्पिन गिनती समय से कम है तो उन्हें भी तेज़ माना जाता है।

यह निर्धारित करने के लिए सबसे महत्वपूर्ण बात यह है कि यदि किसी महत्वपूर्ण अनुभाग पर विवाद आपके आवेदन में पहला आदेश सीमित कारक है। यदि नहीं, तो बस एक महत्वपूर्ण अनुभाग normaly का उपयोग करें और अपने अनुप्रयोगों प्राथमिक प्राथमिक बाधा (या गर्दन) पर काम करते हैं।

यदि महत्वपूर्ण अनुभाग प्रदर्शन महत्वपूर्ण है, तो आप निम्न पर विचार कर सकते हैं।

  1. सावधानीपूर्वक अपने 'गर्म' महत्वपूर्ण वर्गों के लिए स्पिन लॉक गिनती सेट करें। यदि प्रदर्शन सर्वोपरि है, तो यहां का काम इसके लायक है। याद रखें, जबकि स्पिन लॉक उपयोगकर्ता मोड से कर्नेल संक्रमण से बचता है, यह सीपीयू समय को एक क्रूर दर पर खपत करता है - कताई करते समय, सीपीयू समय का उपयोग करने के लिए और कुछ नहीं मिलता है। यदि एक लॉक काफी लंबे समय तक आयोजित किया जाता है, तो कताई धागा वास्तविक ब्लॉक होगा, जो उस सीपीयू को अन्य काम करने के लिए मुक्त कर देगा।
  2. यदि आपके पास पाठक/लेखक पैटर्न है तो Slim Reader/Writer (SRW) locks का उपयोग करने पर विचार करें। यहां नकारात्मकता यह है कि वे केवल Vista और Windows Server 2008 और बाद के उत्पादों पर उपलब्ध हैं।
  3. आप मतदान और विवाद को कम करने के लिए अपने महत्वपूर्ण अनुभाग के साथ condition variables का उपयोग करने में सक्षम हो सकते हैं, केवल आवश्यक होने पर धागे जागते हैं। फिर, ये Vista और Windows Server 2008 और बाद के उत्पादों पर समर्थित हैं।
  4. Interlocked Singly Linked Lists (SLIST) का उपयोग करने पर विचार करें - ये कुशल हैं और 'लॉक फ्री' हैं। इससे भी बेहतर, वे XP और Windows Server 2003 और बाद के उत्पादों पर समर्थित हैं।
  5. अपने कोड की जांच करें - आप कुछ कोड को दोबारा और एक इंटरलॉक ऑपरेशन या सिंक्रनाइज़ेशन और संचार के लिए एसएलआईटीटी का उपयोग करके 'हॉट' लॉक तोड़ने में सक्षम हो सकते हैं।

सारांश में - लॉक विवाद वाले ट्यूनिंग परिदृश्य चुनौतीपूर्ण (लेकिन दिलचस्प!) काम हो सकते हैं। अपने अनुप्रयोगों के प्रदर्शन को मापने और अपने गर्म पथ कहां समझने पर ध्यान केंद्रित करें। Windows Performance Tool kit में xperf टूल्स आपका मित्र है :) हमने अभी विंडोज 7 के लिए माइक्रोसॉफ्ट विंडोज एसडीके में संस्करण 4.5 और .NET Framework 3.5 SP1 (ISO is here, web installer here) जारी किया है। आप xperf टूल्स here के लिए फोरम पा सकते हैं। V4.5 पूरी तरह से Win7, Vista, Windows Server 2008 - सभी संस्करणों का समर्थन करता है।

4

गंभीर संरचनाएं तेज हैं, लेकिन InterlockedIncrement/InterlockedDecrement अधिक है। इस कार्यान्वयन उपयोग नमूना LightweightLock full copy देखें।

कोई विवाद नहीं है, तो स्पिन ताला वास्तव में तेजी से एक Mutex के लिए मोड कर्नेल के लिए जा रहा की तुलना में है:

+0

आप लिंक मर चुके हैं, आप अपना उत्तर – Moe

+1

संपादित करना चाहेंगे LightWeightLock धीमा हो सकता है क्योंकि यह एक स्पिनलॉक है। यह प्राथमिकता उलटा होने के मामले में भी डेडलॉक कर सकता है। –

+0

मैं कोड के छोटे ब्लॉक को सुरक्षित रखने के लिए इंटरलॉक-फ़ंक्शंस (अधिक विशेष रूप से इंटरलाक्ड कॉम्पैयर एक्सचेंज) का उपयोग करता हूं जो अन्य कार्यों को कॉल नहीं करता है। मेरे मामले में मैंने देखा कि इंटरलाक्ड-फ़ंक्शंस क्रिटिकलसेक्शन फ़ंक्शंस जितना तेज़ था (जो मेरे मामले में बहुत महत्वपूर्ण था क्योंकि यह एक छोटा ब्लॉक था जिसे अक्सर निष्पादित किया गया था)। इंटरलाक्ड-फ़ंक्शन का नुकसान यह है कि आप उन्हें घोंसला नहीं दे सकते हैं और आप उन्हें गोपनीय रूप से गलत उपयोग कर सकते हैं (उदा। एक थ्रेड में लॉक करें, किसी अन्य थ्रेड में अनलॉक करें)। – Patrick

1

यहाँ एक तरह से इस पर गौर करने के लिए है।

जब विवाद होता है, तो एक क्रिटिकलसेक्शन सीधे म्यूटक्स का उपयोग करने से थोड़ा महंगा होता है (स्पिनलॉक स्थिति का पता लगाने के लिए अतिरिक्त कार्य के कारण)।

तो यह भारित औसत तक उबाल जाता है, जहां वजन आपके कॉलिंग पैटर्न के विनिर्देशों पर निर्भर करता है। ऐसा कहा जा रहा है कि, यदि आपके पास थोड़ा विवाद नहीं है, तो एक क्रिटिकलसेक्शन बड़ी जीत है। यदि, दूसरी ओर, आप लगातार बहुत सारी विवाद करते हैं, तो आप सीधे म्यूटेक्स का उपयोग करने पर बहुत ही कम दंड का भुगतान करेंगे। लेकिन उस स्थिति में, आपको म्यूटेक्स पर स्विच करके जो लाभ मिलेगा वह छोटा है, इसलिए आप शायद विवाद को कम करने की कोशिश कर रहे हैं।

+0

स्पिनकाउंट को 0 पर सेट करें और कम से कम कभी भी धीमी गति से कम नहीं हो सकता है। – Lothar

+0

हाहा, और यह एक म्यूटेक्स जैसा ही है! –

1

गंभीर खंड म्यूटेक्स से तेज़ है क्यों महत्वपूर्ण अनुभाग कर्नेल ऑब्जेक्ट नहीं है। यह वर्तमान प्रक्रिया की वैश्विक स्मृति का हिस्सा है। म्यूटेक्स वास्तव में कर्नेल में रहता है और म्यूटेक्स्ट ऑब्जेक्ट के निर्माण के लिए कर्नेल स्विच की आवश्यकता होती है लेकिन महत्वपूर्ण खंड के मामले में नहीं। हालांकि महत्वपूर्ण खंड तेजी से है, फिर भी महत्वपूर्ण खंड का उपयोग करते समय कर्नेल स्विच होगा जब धागे राज्य की प्रतीक्षा कर रहे हैं। ऐसा इसलिए है क्योंकि कर्नेल पक्ष में थ्रेड शेड्यूलिंग होती है।

संबंधित मुद्दे