2013-08-25 12 views
6

मैं परावर्तक साथ Roslyn September 2012 CTP को देख रहा हूँ, और मैंने देखा SlidingTextWindow वर्ग निम्नलिखित है:इस मामले में एक ConcurrentQueue का उपयोग क्यों करें?

internal sealed class SlidingTextWindow : IDisposable 
{ 
    private static readonly ConcurrentQueue<char[]> arrayPool = new ConcurrentQueue<char[]>(); 
    private int basis; 
    private readonly LexerBaseCache cache; 
    private char[] characterWindow; 
    private int characterWindowCount; 
    private int characterWindowStart; 
    private int offset; 
    private readonly IText text; 
    private readonly int textEnd; 

    public SlidingTextWindow(IText text, LexerBaseCache cache) 
    { 
     this.text = text; 
     this.basis = 0; 
     this.characterWindowStart = 0; 
     this.offset = 0; 
     this.textEnd = text.Length; 
     this.cache = cache; 
     if (!arrayPool.TryDequeue(out this.characterWindow)) 
     { 
      this.characterWindow = new char[2048]; 
     } 
    } 

    public void Dispose() 
    { 
     arrayPool.Enqueue(this.characterWindow); 
     this.characterWindow = null; 
    } 

    // ... 
} 

मेरा मानना ​​है कि इस वर्ग के उद्देश्य, इनपुट पाठ की सबस्ट्रिंग के लिए तेजी से पहुँच प्रदान करने का उपयोग करना है char[] characterWindow, एक समय में 2048 वर्णों से शुरू होता है (हालांकि characterWindow बढ़ सकता है)। मेरा मानना ​​है कि ऐसा इसलिए है क्योंकि तारों की तुलना में चरित्र सरणी के सबस्ट्रिंग लेने के लिए तेज़ है, जैसे एरिक लिपर्ट seems to indicate on his blog

SlidingTextWindow कक्षा Lexer कक्षा को तत्काल चालू किया जाता है, जो प्रत्येक कॉल SyntaxTree.ParseText पर होता है।

मुझे arrayPool फ़ील्ड के उद्देश्य को समझ में नहीं आता है। इस वर्ग में इसका एकमात्र उपयोग कन्स्ट्रक्टर और निपटान विधियों में है। SyntaxTree.ParseText पर कॉल करते समय, Lexer वर्ग और SlidingTextWindow वर्ग के बनाए गए केवल एक उदाहरण का प्रतीत होता है। उदाहरण के लिए characterWindow को एक उदाहरण के दौरान characterWindow को निकालने का प्रयास करके characterWindow को एनक्यूइंग करके क्या लाभ प्राप्त होता है?

शायद रोज़लिन टीम से कोई मुझे यह समझने में मदद कर सकता है?

उत्तर

16

लाभ यह है कि संग्रह दबाव कम हो जाता है, जिसका समग्र प्रदर्शन पर सकारात्मक प्रभाव पड़ता है।

.NET कचरा कलेक्टर निश्चित रूप से एक सामान्य उद्देश्य कचरा कलेक्टर है। एक कंपाइलर और आईडीई का आवंटन और ऑब्जेक्ट आजीवन पैटर्न आपके औसत लाइन-ऑफ-बिजनेस एप्लिकेशन की तुलना में काफी अलग हैं, और वे असामान्य तरीकों से जीसी पर दबाव डालते हैं।

यदि आप रोज़लिन में देखते हैं तो वहां कई जगहें हैं जहां छोटे सरणी को कैश किया जाता है और जीसी को उन्हें अल्पकालिक कचरा के रूप में पहचानने और उन्हें तुरंत पुनः प्राप्त करने की अनुमति देने के बजाय बाद में फिर से उपयोग किया जाता है। अनुभवजन्य प्रयोगों से पता चलता है कि यह प्रदर्शन में एक मापनीय सुधार देता है।

मैं अपने आवेदन में ऐसा करने की अनुशंसा नहीं करता जब तक कि आपकी प्रोफाइलिंग इंगित न करे कि आपके पास संग्रह दबाव पर एक मापनीय प्रदर्शन समस्या है। आवेदनों के विशाल बहुमत के लिए जीसी बहुत अच्छी तरह से ट्यून किया गया है, और पूलिंग रणनीति का लाभ काफी लागत के लायक नहीं है।

+0

स्मृति को कम करने या बढ़ती गति (या दोनों) के प्राथमिक उद्देश्य के लिए किए गए छोटे सरणी की कैशिंग है? क्या ऐसा मामला है कि एक कंपाइलर/आईडीई के लिए आवश्यक कई एरे के साथ, हर बार एक नई सरणी बनाने में बहुत सारी मेमोरी लगती है? या थ्रेड-सुरक्षित कतार का उपयोग करके गति में वृद्धि होगी और कई धागे सरणी पर कार्य करेंगे? – cubetwo1729

+11

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

+0

@JasonMalinowski 'ConcurrentBag' के बजाय' ConcurrentQueue' चुनने का कोई विशिष्ट कारण? – CodesInChaos

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