2010-03-09 10 views
24

मैंने कैवलिना पुस्तक (एनईटी अनुप्रयोगों के विकास और डिजाइन पर सिफारिशों) को पढ़ा।16 बाइट सी # में संरचना के लिए अनुशंसित आकार क्यों है?

वह कहता है कि एक अच्छी तरह से डिज़ाइन की गई संरचना आकार में 16 बाइट से कम होना चाहिए (प्रदर्शन उद्देश्यों के लिए)।

यह वास्तव में क्यों है?

और (अधिक महत्वपूर्ण) अगर मैं 3.5 (जल्द ही .NET 4.0 होने के लिए) मेरे नेट चलाने Windows के तहत Core i7 पर 64-बिट आवेदन मैं एक ही दक्षता के साथ बड़ा struct हो सकता है   7 x64 (इस सीमा सीपीयू है/ओएस आधारित)?

बस फिर से तनाव के लिए - मुझे जितना संभव हो उतना कुशल संरचना की आवश्यकता है। मैं इसे हर समय ढेर पर रखने की कोशिश करता हूं। आवेदन भारी बहु थ्रेडेड है और उप-मिलीसेकंद अंतराल पर चलता है, और संरचना का वर्तमान आकार 64 बाइट है।

+2

आप क्या मानते हैं कि बनाता है कि ढेर पर अपने डेटा रखने और अधिक कुशल है? ढेर बनाम ढेर में एक कार्यान्वयन विस्तार है।नेट और डेवलपर्स को परवाह नहीं करना चाहिए (देखें http://stackoverflow.com/questions/477101/heap-versus-stack-allocation-implications-net/477333#477333) –

+1

बिना बताए दक्षता के बारे में पूछना कि आप कौन से मीट्रिक का उपयोग कर रहे हैं एक टैड अस्पष्ट यह सबसे कुशल वाहन मांगने जैसा है - यह बताए बिना कि क्या आप अपने यात्रा पर पैसे बचाने की इच्छा रखते हैं, या 30 टन कार्गो परिवहन करने की कोशिश कर रहे हैं। –

+1

Divo आप सिद्धांत में गलत हैं। इस विषय के बाहर मेरा आवेदन बेहतर बनाने के लिए मुझे क्या ख्याल रखना चाहिए। धन्यवाद –

उत्तर

8

केवल आप जानते हैं कि आपके प्रोग्राम में आपके structs का उपयोग कैसे किया जा रहा है। लेकिन अगर कुछ और नहीं है, तो आप हमेशा अपने लिए इसका परीक्षण कर सकते हैं। उदाहरण के लिए, अगर यह अक्सर अन्य कार्यों के लिए पारित किया गया है, पर निम्न बातें स्पष्ट करना हो सकता है:

class MainClass 
{ 
    static void Main() 
    { 
     Struct64 s1 = new Struct64(); 
     Class64 c1 = new Class64(); 
     DoStuff(s1); 
     DoStuff(c1); 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     for (int i = 0; i < 10000; i++) 
     { 
      s1 = DoStuff(s1); 
     } 
     sw.Stop(); 
     Console.WriteLine("Struct {0}", sw.ElapsedTicks); 
     sw.Reset(); 

     sw.Start(); 
     for (int i = 0; i < 10000; i++) 
     { 
      c1 = DoStuff(c1); 
     } 
     sw.Stop(); 
     Console.WriteLine("Class {0}", sw.ElapsedTicks); 
     sw.Reset(); 

     Console.ReadLine(); 
    } 
} 

साथ:

public class Class64 
{ 
    public long l1; 
    public long l2; 
    public long l3; 
    public long l4; 
    public long l5; 
    public long l6; 
    public long l7; 
    public long l8; 
} 
public struct Struct64 
{ 
    public long l1; 
    public long l2; 
    public long l3; 
    public long l4; 
    public long l5; 
    public long l6; 
    public long l7; 
    public long l8; 
} 

प्रतिनिधि structs/वर्गों के साथ बात की इस तरह की कोशिश करो, और देखो क्या परिणाम आपको मिल ।(मेरी मशीन पर, परीक्षण के ऊपर, कक्षा ~ 3 गुना तेज लगती है)

+1

वही .. .. 16 बाइट्स के लिए मेरे पास 24/18 (स्ट्रक्चर बनाम वर्ग) था, 32 बाइट्स 30/17 vor 64 बाइट्स 42/18 के लिए। ऐसा लगता है कि सीपीयू/बस चौड़ाई के बावजूद 16 बाइट वास्तव में उचित सीमा है। –

+1

बेंचमार्क को लूप के साथ बदलें कि एक स्ट्रक्चर के लिए 'int (int i = 0; i <100000; i ++) {mystruct.l1 + = i;} 'है, और उसके बाद इसे स्ट्रक्चर और क्लास के लिए' int i = 0; i <100000; i ++) {mything = new जो कुछ भी (mything.l1 + i, mything.l2, mything.l3, mything.l4, mything.l5, mything.l6, mything.l7, mything.l8)}; 'सरल म्यूटेबल स्ट्रक्चर एक मील से जीत जाएगा, निष्पादन समय के साथ जो फ़ील्ड की संख्या से स्वतंत्र है। "अपरिवर्तनीय-संरचना-शैली" संस्करण कक्षा संस्करण को काफी मार्जिन से बेहतर बनाने के लिए उपयुक्त है, हालांकि; दर्जनों 'लंबे' फ़ील्ड जोड़ना उसमें बदलाव नहीं करेगा। – supercat

4
  • बड़ी संरचना उतनी कुशल नहीं है, लेकिन फिर .... यदि आपके पास अधिक डेटा है, तो आपके पास यह है। वहां दक्षता के बारे में बात करने का कोई मतलब नहीं है।

  • 64 बाइट ठीक होना चाहिए।

  • मुख्य कारण संभवतः कॉपी ऑपरेशन है .... यदि संरचना बड़ी है तो आईआईआरसी धीमी हो जाती है। और इसे काफी हद तक कॉपी किया जाना चाहिए।

मैं करूंगा सामान्य रूप से यहां एक वर्ग का उपयोग करते हुए सलाह;) लेकिन struct की सामग्री को जानने के बिना, यह एक छोटे मुश्किल है।

+0

टॉम धन्यवाद दोस्त। क्या आप कृपया कुछ जानकारी प्रदान कर सकते हैं जो बताता है कि 64 सीट्स मेरे सीपीयू के लिए क्यों ठीक है? बीटीडब्ल्यू - संरचना ताले से बचने के लिए प्राकृतिक पसंद थी। यदि मैं अपरिवर्तनीय कक्षा या ताले का उपयोग करता हूं तो विकास की लागत बहुत अधिक हो जाएगी ... तो कक्षा बनाम संरचना को पास करने दें .. –

+0

ठीक है, कोई संदर्भ नहीं है। मैं सोचता हूं कि 64 बाइट्स बहुत ज्यादा नहीं हो सकते हैं। यह वास्तव में उस डेटा पर निर्भर करता है जो वहां है। मैं सामान्य रूप से इस तरह के structs का उपयोग नहीं करते हैं। मेरे पास एक वित्तीय व्यापार ऐप है (डेटा के टन के माध्यम से - छोटे, लगभग 64 बाइट्स, somtiems 50.000+ आइटम प्रति सेकंड आने) और मैं कक्षाओं का उपयोग करता हूं। – TomTom

+0

मैं संरचना बनाम वर्ग के बारे में गलत हो सकता हूं ... इसे देखने के लायक हो सकता है। –

20

आप पुस्तक (कम से कम 2 संस्करण) गलत तरीके से गलत कर रहे हैं। जेफरी रिक्टर राज्यों मूल्य प्रकार 16 से अधिक बाइट्स अगर कर सकते हैं:

आप इरादा नहीं है उन्हें अन्य तरीकों के पास या करने के लिए और एक संग्रह वर्ग से उन्हें कॉपी करने के लिए।

इसके अतिरिक्त एरिक Gunnerson (16 बाइट सीमा के बारे में) कहते हैं

उपयोग एक ट्रिगर के रूप में इस निर्देश अधिक जांच करने के लिए।

यह सच नहीं है कि एक संरचना "आकार में 16 बाइट से कम होनी चाहिए"। यह सब उपयोग पर निर्भर करता है।

यदि आप संरचना बना रहे हैं और इसे भी उपभोग कर रहे हैं और प्रदर्शन के बारे में चिंतित हैं तो एक संरचना बनाम कक्षा की तुलना में एक प्रोफाइलर का उपयोग करें ताकि यह देखने के लिए कि कौन सा आपके लिए सबसे अच्छा काम करता है।

+1

मैंने कहा - इसे एक अच्छा डिजाइन माना जाना चाहिए। कृपया पूरी वाक्य उद्धृत करें। मेरे शब्दों को आपने कैसे वितरित किया है, इस बारे में है - संरचना 16 बाइट या उससे कम होनी चाहिए ... नहीं, यह नहीं है! मैंने कल इस पुस्तक को पढ़ा था। मुझे पता है कि रिक्टर ने क्या कहा और यह मेरे आवेदन पर लागू नहीं है इसलिए मैंने इसे केवल अनदेखा किया ... क्योंकि विषय पुस्तक पर चर्चा नहीं करना है, लेकिन मुझे अपने आवेदन को और अधिक कुशल बनाने में मदद करें बहुत बहुत धन्यवाद! और गुनरसन के लिए - यह वही है जो मैं यहां करने की कोशिश कर रहा हूं - आगे की जांच करें! –

+0

@ मैक्सिमा 120। मैंने आपके शब्दों को विकृत नहीं किया। आपने पुस्तक को गलत तरीके से गलत किया, मैंने आपको सही किया। पुस्तक उन structs से बचने के लिए राज्य करती है जिनके पास 16 बाइट्स के तहत एक आवृत्ति आकार नहीं है (फिर चेतावनी जोड़ता है)। यह स्पष्ट रूप से एक जैसा नहीं है "अच्छी तरह से डिज़ाइन किया गया संरचना आकार में 16 बाइट से कम होना चाहिए"। – RichardOD

1

मुझे लगता है कि एक और महत्वपूर्ण बिंदु यह है कि यदि आपके पास लाखों structs के साथ एक सूची है, तो यह अभी भी ढेर पर केवल एक स्मृति आवंटन है, जबकि इसमें दस लाख वर्गों के साथ सूची में लगभग दस लाख अलग ढेर वस्तुओं की जा रही है। कचरा संग्रह भार दोनों मामलों में काफी अलग है। इस दृष्टिकोण से, संरचना आगे आ सकती है।

+0

यदि आप स्टोर करते हैं तो आप ढेर आवंटित ऑब्जेक्ट में structs हैं, तो आप उन्हें आवंटित ढेर भी बेहतर तरीके से रखते हैं! अन्यथा चीजें वास्तव में मजेदार होती हैं जब आपका वर्तमान स्टैकफ्रेम मर जाता है (स्टैक आवंटित ऑब्जेक्ट्स के साथ) और आप ढेर आवंटित ऑब्जेक्ट के माध्यम से उन्हें एक्सेस करने का प्रयास करते हैं। यही कारण है कि सभी सदस्यों (मूल्य टाइप सहित) ढेर –

+2

@Rune FS - सत्य पर संग्रहीत हैं, लेकिन structs के पूरे वेक्टर स्मृति के एक बड़े, संगत ब्लॉक में होने जा रहे हैं। व्यक्तिगत जीवनकाल के साथ दस लाख छोटे टुकड़ों के विरोध में। – Tarydon

+0

यह नोड-आधारित सूची कार्यान्वयन के साथ सच है। हालांकि, 'System.Collections.Generic.List 'आंतरिक रूप से' टी [] 'द्वारा समर्थित है जो आवश्यकतानुसार आकार बदलता है। –

2

असेंबली भाषा प्रोग्रामिंग करते समय मैंने जो कुछ सीखा, वह यह था कि आप 8 या 16 बाइट सीमाओं पर अपने structs (और अन्य डेटा) को संरेखित करते हैं (वास्तव में एमएएसएम में इसके लिए प्रीप्रोसेसर कमांड है)। मेमोरी में चारों ओर चीजें संग्रहीत या स्थानांतरित करते समय इसका कारण काफी तेज़ स्मृति पहुंच है। आकार में 16 बाइट्स के तहत अपने structs को बनाए रखना सुनिश्चित करेगा कि यह स्मृति संरेखण सफलतापूर्वक किया जा सकता है क्योंकि कुछ भी संरेखण सीमा पार नहीं करेगा।

हालांकि मैं बात इस तरह की उम्मीद होती है मोटे तौर पर जब नेट ढांचे का उपयोग कर आप से छिपाना चाहता है। यदि आपके structs 16 बाइट से बड़े थे तो मैं फ्रेमवर्क (या जेआईटी कंपाइलर) को 32 बाइट सीमाओं पर अपने डेटा को संरेखित करने की अपेक्षा करता हूं, और इसी तरह। उन पुस्तकों में टिप्पणियों के कुछ सत्यापन को देखना दिलचस्प होगा, और देखें कि गति में अंतर क्या है।

+1

structs का लेआउट एक रहस्य नहीं है। लेआउटस्ट्रक्चर सी # विशेषता के लिए देखो .. उदा। http://www.vsj.co.uk/articles/display.asp?id=501 –

+0

यह एक अच्छा लिंक है।मैं ढांचे/जिटर के व्यवहार के बारे में और बात कर रहा था, और सोच रहा था कि क्यों 16 ऐसा जादू संख्या था (और क्या यह अभी भी इतना जादू है या फिर इसे बढ़ाया गया है या अप्रासंगिक बना दिया गया है)। – slugster

7

JIT कम्पाइलर संरचनाओं जो एक न्यूनतम सीमा से छोटे हैं कॉपी करने के लिए विशेष-केस कोड पैदा करता है, और कुछ हद तक एक-धीमी सामान्य प्रयोजन बड़ों के लिए का निर्माण। मैं अनुमान लगाता हूं कि जब वह सलाह लिखी गई थी, तो सीमा 16 बाइट थी, लेकिन आज के 32-बिट ढांचे में यह 24 बाइट्स लगता है; यह 64-बिट कोड के लिए बड़ा हो सकता है।

कहा गया है कि, किसी भी आकार वर्ग वस्तु बनाने की लागत एक struct जो एक ही डेटा रखता कॉपी करने की लागत की तुलना में काफी अधिक है। यदि कोड 32 बाइट के लायक फ़ील्ड के साथ क्लास ऑब्जेक्ट बनाता है और फिर उस ऑब्जेक्ट के संदर्भ को 1,000 बार गुजरता है या अन्यथा प्रतिलिपि बनाता है, 1,000 32-बाइट संरचनाओं की प्रतिलिपि बनाने के बजाय 1,000 ऑब्जेक्ट संदर्भों की प्रतिलिपि बनाने से समय बचत की संभावना अधिक होगी कक्षा वस्तु बनाना। यदि, हालांकि, ऑब्जेक्ट इंस्टेंस को केवल दो बार प्रतिलिपि बनाने के बाद छोड़ दिया जाएगा, ऑब्जेक्ट बनाने की लागत शायद 32-बाइट संरचना को दो बार कॉपी करने की लागत के एक बड़े मार्जिन से अधिक हो जाएगी।

भी ध्यान दें कि यह कई मामलों में मूल्य से संरचनाओं के आसपास गुजर या अन्यथा प्रचुरता से, उन्हें कॉपी करने अगर एक प्रयासों ऐसा करने के लिए से बचने के लिए संभव है। एक विधि के लिए ref पैरामीटर के रूप में संरचना के किसी भी आकार को पास करना, उदाहरण के लिए, केवल एक-मशीन-शब्द (4 या 8 बाइट्स) पते को पारित करने की आवश्यकता होती है। क्योंकि .net में const ref अवधारणा की किसी भी प्रकार की कमी नहीं है, केवल लिखने योग्य फ़ील्ड या वेरिएबल्स को इस तरह से पारित किया जा सकता है, और System.Array के अलावा संग्रह - नेटवाइड ref द्वारा सदस्यों तक पहुंचने का कोई मतलब नहीं है। यदि कोई सरणी या कस्टम संग्रह का उपयोग करने के इच्छुक है, हालांकि, यहां तक ​​कि विशाल (100 बाइट्स या अधिक) संरचनाओं को भी बहुत कुशलता से संसाधित किया जा सकता है। कई मामलों में, एक अपरिवर्तनीय वर्ग के बजाय संरचना का उपयोग करने का प्रदर्शन लाभ encapsulated डेटा के आकार के साथ बढ़ सकता है।

2

वास्तव में, एक 64-बिट मशीन पर 32 बाइट्स अधिकतम आकार struct डेटा के लिए उपयोग करने के लिए है। मेरे परीक्षणों से 32 बाइट स्ट्रक्चर (चार लम्बाई) के साथ-साथ ऑब्जेक्ट संदर्भ भी करता है।

आप यहाँ परीक्षण अपने आप को चलाने के परीक्षण कोड प्राप्त कर सकते हैं और: https://github.com/agileharbor/structBenchmark

परीक्षण पिछले कुछ structs की एक बड़ी संख्या को कॉपी/एक से दूसरे सरणी से वस्तुओं, और आप देखने के लिए जहां वर्ग में सक्षम हैं आठ लम्बाई के साथ संरचना का प्रदर्शन करता है, लेकिन यह चार लम्बाई के साथ संरचना के समान है।

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