2011-08-20 8 views
9

मैंने छोटे परीक्षण कार्यक्रम लिखे हैं और आश्चर्यचकित क्यों हैं lock {} समाधान लॉक-फ्री से तेज़ प्रदर्शन करता है लेकिन स्थिर चर पर [ThreadStatic] विशेषता के साथ।.NET: थ्रेडस्टैटिक बनाम लॉक {}। ThreadStaticAttribute प्रदर्शन को कम क्यों करता है?

[ThreadStatic] टुकड़ा:

[ThreadStatic] 
private static long ms_Acc; 
public static void RunTest() 
{ 
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start(); 
    int one = 1; 
    for (int i = 0; i < 100 * 1000 * 1000; ++i) { 
     ms_Acc += one; 
     ms_Acc /= one; 
    } 
    stopwatch.Stop(); 
    Console.WriteLine("Time taken: {0}", stopwatch.Elapsed.TotalSeconds); 
} 

ताला {} स्निपेट:

private static long ms_Acc; 
private static object ms_Lock = new object(); 
public static void RunTest() 
{ 
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start(); 
    int one = 1; 
    for (int i = 0; i < 100 * 1000 * 1000; ++i) { 
     lock (ms_Lock) { 
      ms_Acc += one; 
      ms_Acc /= one; 
     } 
    } 
    stopwatch.Stop(); 
    Console.WriteLine("Time taken: {0}", stopwatch.Elapsed.TotalSeconds); 
} 

मेरी मशीन पहला टुकड़ा पर 4.2 सेकंड लेता है; दूसरा - 3.2 सेकंड, जो 1 सेकंड तेज है। थ्रेडस्टैटिक और लॉक के बिना - 1.2 सेकंड।

मुझे उत्सुकता है कि [ThreadStatic] इस सरल उदाहरण में विशेषता प्रोग्राम निष्पादन समय में इतनी सारी जोड़ती है?

अद्यतन: मुझे बहुत खेद है, लेकिन ये परिणाम DEBUG निर्माण के लिए हैं। RELEASE के लिए मुझे एक पूरी तरह से अलग संख्या मिली: (1.2; 2.4; 1.2)। DEBUG संख्याओं के लिए (4.2; 3.2; 1.2) थे।

तो, RELEASE बिल्ड के लिए कोई [ThreadStatic] प्रदर्शन जुर्माना नहीं लगता है।

+0

यही कारण है कि मैं अपने के quadcore पर दिखाई नहीं दे रहा है। अगर मैं किसी भी सीपीयू पर रिलीज संकलित करता हूं तो मुझे पहले स्निपेट के लिए 0.81 और दूसरे के लिए 4.5s मिलते हैं।थ्रेड सुरक्षा के बिना मामूली मामला 0.46 लेता है। – FuleSnabel

+0

आप सही हैं। मैंने 'डीबग' से 'रिलीज' मोड में स्विच किया और आपके परिणामों के समान ही मिला। – Roman

+0

यह समझने के लिए विघटित कोड को पढ़ने में मदद कर सकता है कि आपको आश्चर्यजनक परिणाम क्यों मिलते हैं। – FuleSnabel

उत्तर

6

रिलीज के लिए निर्माण लगभग कोई [थ्रेडस्टैटिक] प्रदर्शन दंड (आधुनिक CPUs पर केवल मामूली जुर्माना) लगता है।

यहां ms_Acc += one के लिए असेंबली कोड आता है; RELEASE के लिए अनुकूलन सक्षम है:

नहीं[ThreadStatic], DEBUG:

00000060 mov   eax,dword ptr [ebp-40h] 
00000063 add   dword ptr ds:[00511718h],eax 

नहीं[ThreadStatic], RELEASE:

00000051 mov   eax,dword ptr [00040750h] 
00000057 add   eax,dword ptr [rsp+20h] 
0000005b mov   dword ptr [00040750h],eax 

[ThreadStatic], DEBUG:

012,351,
00000066 mov   edx,1 
0000006b mov   ecx,4616E0h 
00000070 call  664F7450 
00000075 mov   edx,1 
0000007a mov   ecx,4616E0h 
0000007f mov   dword ptr [ebp-50h],eax 
00000082 call  664F7450 
00000087 mov   edx,dword ptr [eax+18h] 
0000008a add   edx,dword ptr [ebp-40h] 
0000008d mov   eax,dword ptr [ebp-50h] 
00000090 mov   dword ptr [eax+18h],edx 

[ThreadStatic], RELEASE:

00000058 mov   edx,1 
0000005d mov   rcx,7FF001A3F28h 
00000067 call  FFFFFFFFF6F9F740 
0000006c mov   qword ptr [rsp+30h],rax 
00000071 mov   rbx,qword ptr [rsp+30h] 
00000076 mov   ebx,dword ptr [rbx+20h] 
00000079 add   ebx,dword ptr [rsp+20h] 
0000007d mov   edx,1 
00000082 mov   rcx,7FF001A3F28h 
0000008c call  FFFFFFFFF6F9F740 
00000091 mov   qword ptr [rsp+38h],rax 
00000096 mov   rax,qword ptr [rsp+38h] 
0000009b mov   dword ptr [rax+20h],ebx 
+2

लगता है जैसे [थ्रेडस्टैटिक], डीईबीयूजी 32 बिट और [थ्रेडस्टैटिक] है, रिलीज 64 बिट है। – kerem

-1

आपके पास कोड की दो पंक्तियां हैं जो ms_Acc अद्यतन करती हैं। lock मामले में, आपके पास ThreadStatic मामले में दोनों के आस-पास एक एकल लॉक है, यह प्रत्येक बार ms_Acc तक पहुंच के लिए होता है, यानी आपके लूप के प्रत्येक पुनरावृत्ति के लिए दो बार। यह आम तौर पर lock का उपयोग करने का लाभ है, आपको अपनी इच्छित ग्रैन्युलरिटी चुननी होगी। मैं अनुमान लगा रहा हूं कि रिलीज बिल्ड ने इस अंतर को अनुकूलित किया है।

मुझे यह देखने में दिलचस्पी होगी कि प्रदर्शन बहुत समान या समान हो जाता है, यदि आप ms_Acc पर एक ही पहुंच में लूप को बदलते हैं।

+0

मुझे यकीन नहीं है कि मंदी की वजह से कोड की दो पंक्तियों की वजह से 'ms_Acc' अपडेट किया गया है। मैंने केवल 'ms_Acc/= one' जोड़ा क्योंकि 'ms_Acc + = one' बेहद तेज़ है और समय को मापना मुश्किल बनाता है। मुझे नहीं लगता कि 'थ्रेडस्टैटिक]' किसी भी तरह चर के उपयोग को सिंक्रनाइज़ करता है - इसका उद्देश्य सिंक्रनाइज़ेशन से बचने के लिए है (क्योंकि अन्य थ्रेड "' [shreadStatic] 'variable" नहीं देख सकते हैं) और, thu, प्रदर्शन में वृद्धि। – Roman

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