2010-08-18 16 views
6

मेरे पास बाइनरी फाइलों का एक बहुत बड़ा सेट है जहां वीडियो के कई हजार कच्चे फ्रेम अनुक्रमिक रूप से पढ़े और संसाधित किए जा रहे हैं, और अब मैं इसे अनुकूलित करने के लिए देख रहा हूं क्योंकि यह अधिक CPU- बाध्य है I/O-bound से.NET बाइनरी फ़ाइल पढ़ें प्रदर्शन

फ्रेम वर्तमान में इस तरह से पढ़ा जा रहा है, और मुझे लगता है यह सबसे बड़ी दोषी है:

private byte[] frameBuf; 
BinaryReader binRead = new BinaryReader(FS); 

// Initialize a new buffer of sizeof(frame) 
frameBuf = new byte[VARIABLE_BUFFER_SIZE]; 
//Read sizeof(frame) bytes from the file 
frameBuf = binRead.ReadBytes(VARIABLE_BUFFER_SIZE); 

यह नेट के लिए से बचने के लिए मैं/हे फिर से संगठित में बहुत अधिक अंतर बना सकते हैं प्रत्येक फ्रेम के साथ इन सभी नए बाइट सरणी बनाना?

.NET की स्मृति आवंटन तंत्र की मेरी समझ कमजोर है क्योंकि मैं शुद्ध सी/सी ++ पृष्ठभूमि से आ रहा हूं। मेरा विचार है कि एक स्थिर बफर क्लास को साझा करने के लिए इसे फिर से लिखना है जिसमें फ्रेम के वास्तविक आकार को ट्रैक करने वाले पूर्णांक वाले एक बहुत बड़े साझा बफर शामिल हैं, लेकिन मुझे वर्तमान कार्यान्वयन की सादगी और पठनीयता से प्यार है और यदि इसे सीएलआर पहले से ही इसे किसी तरह से संभालता है, मुझे पता नहीं है।

किसी भी इनपुट की बहुत सराहना की जाएगी।

+5

क्या आप यह सुनिश्चित करने के लिए एक प्रोफाइलर चलाते हैं कि प्रदर्शन हिट अन्य स्रोतों से नहीं आती है? या आप अभी गए और मान लिया "तो शायद यह है"? –

+0

हाय डेविड, मैंने कुछ बार प्रदर्शन प्रोफाइलर चलाया और यह विशेष तरीका मेरा सबसे महंगा है। इसलिए मैं यह देखने के लिए देख रहा हूं कि यह "नया बाइट []" विधि .NET में एक स्पष्ट प्रदर्शन हत्यारा है या नहीं। एक सी प्रोग्रामर के रूप में, यह प्रत्येक बफर के लिए हजारों "मॉलोक" कथन के समान दिखता है, जो निश्चित रूप से फिर से उपयोग किए जाने वाले बफर से धीमा होगा। – rnd

उत्तर

7

यदि आप binRead.ReadBytes का उपयोग करते हैं तो आपको frameBuf में प्रवेश करने की आवश्यकता नहीं है - आपको एक नया बाइट सरणी वापस मिल जाएगी जो आपके द्वारा अभी बनाई गई एक ओवरराइट करेगा। हालांकि, प्रत्येक पढ़ने के लिए यह एक नई सरणी बनाता है।

यदि आप बाइट एरे का एक समूह बनाने से बचना चाहते हैं, तो आप binRead.Read का उपयोग कर सकते हैं, जो बाइट्स को उस सरणी में डाल देगा जो आप इसे देते हैं। यदि अन्य धागे सरणी का उपयोग कर रहे हैं, हालांकि, वे इसकी सामग्री को उनके सामने सही रूप से बदल देंगे। सुनिश्चित करें कि आप गारंटी दे सकते हैं कि आप इसे पुन: उपयोग करने से पहले बफर के साथ कर चुके हैं।

+0

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

1

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

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

आपका परीक्षण अब खुलासा करेगा कि आप बफर आवंटित करने और डेटा को पढ़ने में व्यतीत समय की मात्रा से संबंधित डेटा को संसाधित करने में काफी समय व्यतीत करते हैं।

यह शायद ही कभी वास्तविक उपयोग में repro होगा। डेटा अभी तक कैश में नहीं होगा, अब स्लगी डिस्क ड्राइव को डेटा (कई मिलीसेकंड) की तलाश करने की आवश्यकता है और इसे डिस्क प्लेटर (दो दर्जन मेगाबाइट प्रति सेकंड, सर्वोत्तम रूप से) को पढ़ने की आवश्यकता है। डेटा को पढ़ने से अब चार गुना अधिक अच्छा समय लगता है। यदि आप प्रसंस्करण चरण को तेज़ी से दो बार करने में कामयाब रहे हैं, तो आपका प्रोग्राम वास्तव में केवल 0.05% तेज होगा। दे या ले।

+0

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

+2

ये बफर शायद 85KB से अधिक बड़े हैं। जो उन्हें LOH में आवंटित किया जाता है। वे थोड़ी देर के लिए वहां फंस जाएंगे, यह एक जन # 2 संग्रह लेता है। कुछ भी मुफ्त में नहीं आता है, जब वे बड़े होते हैं तो बफर का पुन: उपयोग करना .NET में भी एक अच्छी रणनीति है। –

+0

यदि आप डिस्क से लोड करने के लिए फ़ाइल को मजबूर करना चाहते हैं, तो इस फ़ाइल में दिखाई देने वाले विंडोज फ़ाइल कैश को साफ़ करें: http://stackoverflow.com/q/478340/80525 – BKewl

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