2009-07-05 20 views
5

मेरे पास एक छोटा प्रोग्राम है जो डिस्क पर फ़ाइलों को पढ़ता है और लिखता है। इसे सबसे सरल स्तर पर तोड़कर, यह एक फ़ाइल स्ट्रीम से बाइट पढ़ता है और उन्हें दूसरे को लिखता है। यह अपने कर्तव्यों को ठीक करता है, लेकिन यह सबसे तेज़ चीज नहीं है।.NET में डिस्क को पढ़ने/लिखने का सबसे तेज़ तरीका क्या है?

मैंने अन्य अनुप्रयोगों को देखा है जो अद्भुत गति में गीगाबाइट या अधिक पढ़ने/लिखने के माध्यम से फाड़ सकते हैं। जाहिर है, वे थोड़ा .NET ऐप की तुलना में धातु के करीब काम कर रहे हैं।

डिस्क से स्ट्रीमिंग के लिए सबसे कुशल .NET API क्या हैं? तेजी से डिस्क पहुंच के लिए क्या Win32 एपीआई उपलब्ध हैं (और पी/invoking के लायक)?

+3

मुझे नहीं पता कि WinAPI कॉल .NET कक्षाओं से कहीं अधिक तेज़ क्यों होना चाहिए - बाद में, बाद में आंतरिक रूप से पूर्व का उपयोग करें। इसके अलावा, क्या एक मेमोरी-मैप की गई फ़ाइल (http://en.wikipedia.org/wiki/Memory_mapped_file) शायद उपयुक्त हो? – Noldorin

+0

Dot.net को फ़ाइल में लिखने के एक से अधिक तरीके क्यों होंगे? फ़ाइलों को पढ़ना और लिखना बहुत ही बुनियादी है और इसे "तेज़" और "धीमा" रूप में कोई समझ नहीं आता है - क्योंकि कोई भी "धीमी" संस्करण का उपयोग नहीं करेगा क्योंकि दोनों के पास समान उद्देश्यों हैं। –

+0

आधे घंटे के भीतर मैं एक परीक्षण की तुलना कर सकता था .नेट फ़ाइल ऑपरेशंस (बेवकूफ कार्यान्वयन, शायद, जो प्रश्न का हिस्सा है) और गहन आईओ (जैसे कि क्विकएपी) के साथ एक मूल आवेदन जो .NET से दरवाजे को उड़ा देगा एप्लिकेशन। यह सवाल का मुद्दा है - आप .NET में इष्टतम डिस्क थ्रूपुट कैसे प्राप्त करते हैं? – Will

उत्तर

10

फास्ट फ़ाइल I/O आपके द्वारा बनाए गए विशिष्ट API कॉल के बारे में कम है, बल्कि इसके बजाय आप अपने एप्लिकेशन को I/O के साथ काम करने के तरीके के बारे में बताते हैं।

आप उदाहरण के लिए, एक अनुक्रमिक तरीके से किसी एकल थ्रेड पर अपने आई/ओ कार्यों के सभी प्रदर्शन कर रहे हैं

    स्मृति स्मृति में
  1. प्रक्रिया ब्लॉक किसी भी तरह
  2. बाहर
  3. लिखें ब्लॉक में
  4. पढ़ें ब्लॉक
  5. दोहराएँ दायर करने के लिए जब तक किया ...

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

  1. एक (या अधिक) कार्यकर्ता धागे डिस्क से डाटा पढ़ने के लिए और उन्हें एक साझा इनपुट कतार
  2. एक (या अधिक) कार्यकर्ता धागे से साझा ब्लॉक पढ़ने के लिए जोड़ने इनपुट कतार, उन्हें संसाधित करें और उन्हें साझा आउटपुट कतार
  3. साझा करें (एक और अधिक) कार्यकर्ता धागे साझा आउटपुट कतार से संसाधित संसाधित पढ़ते हैं और उचित आउटपुट फ़ाइलों को लिखते हैं।

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

यदि आपके पास वास्तव में समय है और सिस्टम से प्रदर्शन के हर औंस को निचोड़ना चाहते हैं, तो आप थ्रूपुट को अधिकतम करने के लिए I/O completion ports - अपेक्षाकृत कम-स्तरीय API का उपयोग भी कर सकते हैं।

शुभकामनाएं।

1

क्या आपने यह निर्धारित करने के लिए अपना आवेदन प्रोफाइल किया है कि डिस्क I/O बाधा थी या नहीं?

हार्डवेयर किस तरह आप इस पर चल रहे हैं? हार्डवेयर कॉन्फ़िगरेशन क्या है?

.NET में आप System.IO.File नामस्थान का प्रयास कर सकते हैं।

Win32 फ़ंक्शंस के लिए आप CreateFile, WriteFile, ReadFile श्रृंखला का प्रयास कर सकते हैं।

एक उदाहरण:

http://msdn.microsoft.com/en-us/library/bb540534(VS.85).aspx

यह निश्चित रूप से कटौती और सूखे नहीं है। यह सब परीक्षण और मापने के बारे में है।

+0

डिस्क IO समस्या होने पर मैं व्यक्तिगत रूप से * बहुत * आश्चर्यचकित हूं ... मुझे किसी भी .NET primitives के साथ डिस्क IO को अधिकतम करने में कोई समस्या नहीं हुई है ... (जब तक वह शायद .NET 1 चला रहा हो मेरा मानना ​​है कि फ़ाइल स्ट्रीम में अंतर्निर्मित बफर नहीं था) – jerryjvl

+1

सवाल यह नहीं था कि कैसे, लेकिन कितना तेज़ है। System.IO.File (कटाक्ष, ftw) पर टिप के लिए धन्यवाद। – Will

0

BinaryReader और एक उपयुक्त बफर आकार के साथ BinaryWriter बहुत तेजी से कर रहे हैं। यदि आप संरचनाओं में पढ़ रहे हैं, तो in this article वर्णित असुरक्षित दृष्टिकोण आपको तेजी से पढ़ेगा, और लेखन समान है। मैं डबल-चेक करने के सुझाव के साथ भी सहमत हूं कि I/O वास्तव में बाधा है। मैं पहली बार इस तरह की गलती के कारण उस लेख में आया था।

6

नेट फ़ाइल समर्थन काफी तेजी से (देशी Win32 कार्यों की तुलना में) है। कई विकल्प आपके प्रदर्शन को सुधारने में मदद कर सकते:

  1. यदि आपका पढ़ें/लिखें अनुक्रमिक है, उपयुक्त रणनीति लागू करके कैशिंग प्रबंधक मदद - RandomAccess or SequentalScan, प्रदान करते हैं जब FileStream
  2. instantiating के भंडारण के लिए एक बड़ा स्मृति बफर उपयोग करने पर विचार डेटा पढ़ें
  3. यदि आप कई छोटी फाइलों की प्रतिलिपि बनाते हैं, तो आप पहले एक बार मेमोरी बफर में कई फाइलें पढ़ सकते हैं (देखें 2), और फिर डिस्क
  4. पर फ़ाइलें लिखें यदि विभिन्न स्थानों पर स्रोत और गंतव्य स्ट्रीम स्थित हैं (वह एक ही हार्ड ड्राइव पर नहीं है, शायद नेटवर्क पर एक फ़ाइल, दूसरी तरफ एक स्थानीय हार्ड ड्राइव, आदि), आप गति-अप करने के लिए अतुल्यकालिक पैटर्न का उपयोग कर सकते हैं, BeginRead का उपयोग करके डेटा को पढ़ने, तो BeginWrite का उपयोग कर डेटा लिखते हैं, और जबकि डेटा BeginRead का उपयोग करके पढ़ा अगले डेटा ब्लॉक लिखा जा रहा है।
  5. अगर आप अभी भी लगता है कि प्रदर्शन पर्याप्त नहीं है (हालांकि अपने परीक्षण से यह equatable या यहां तक ​​कि तेजी से आंतरिक विंडोज कॉपी है), तो आप CopyFileEx Win32 फ़ंक्शन का उपयोग कर सकते हैं (लेकिन इस समारोह फ़ाइलें, नहीं धाराओं के साथ काम करता है)।
+1

प्रश्न का हिस्सा इसे सही तरीके से उपयोग करने के बारे में है, जो यह उत्तर कम से कम पूरा करने का प्रयास करता है। धन्यवाद। – Will

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