2008-10-25 19 views
117

मेरे पास एक विधि है जो एक फ़ाइल से संदेशडिगस्ट (हैश) बनाता है, और मुझे इसे कई फाइलों (> = 100,000) में करने की आवश्यकता है। प्रदर्शन को अधिकतम करने के लिए फ़ाइलों से पढ़ने के लिए बफर को कितना बड़ा उपयोग करना चाहिए?FileInputStream का उपयोग करते समय आप आदर्श बफर आकार को कैसे निर्धारित करते हैं?

MessageDigest md = MessageDigest.getInstance("SHA"); 
FileInputStream ios = new FileInputStream("myfile.bmp"); 
byte[] buffer = new byte[4 * 1024]; // what should this value be? 
int read = 0; 
while((read = ios.read(buffer)) > 0) 
    md.update(buffer, 0, read); 
ios.close(); 
md.digest(); 

प्रवाह क्षमता को अधिकतम करने के बफर के आदर्श आकार क्या है:

अधिकांश हर कोई बुनियादी कोड (जो मैं यहाँ सिर्फ मामले में दोहराने की आवश्यकता होगी) से परिचित है? मुझे पता है कि यह सिस्टम निर्भर है, और मुझे पूरा यकीन है कि इसका ओएस, फाइलसिस्टम, और एचडीडी निर्भर है, और मिश्रण में अन्य हार्डवेयर/सॉफ्टवेयर हो सकता है।

(मैं कहना चाहिए कि मैं कुछ जावा के लिए नया हूँ, इसलिए यह सिर्फ कुछ जावा API कॉल के बारे में मैं नहीं जानता हो सकता है।)

संपादित करें: मैं समय से आगे पता नहीं है इस तरह के सिस्टम का उपयोग किया जाएगा, इसलिए मैं पूरी तरह से नहीं मान सकता। (मुझे लगता है कि कारण के लिए जावा का उपयोग कर रहा हूँ।)

संपादित करें: कोड ऊपर try..catch तरह बातें याद आ रही है बनाने के लिए पद छोटे

उत्तर

171

इष्टतम बफर आकार कई चीजों से संबंधित है: फ़ाइल सिस्टम ब्लॉक आकार, सीपीयू कैश आकार और कैश विलंबता।

अधिकांश फ़ाइल सिस्टम 4096 या 8192 के ब्लॉक आकारों का उपयोग करने के लिए कॉन्फ़िगर किए गए हैं। सिद्धांत रूप में, यदि आप अपने बफर आकार को कॉन्फ़िगर करते हैं तो आप डिस्क ब्लॉक से कुछ बाइट्स पढ़ रहे हैं, फाइल सिस्टम के साथ ऑपरेशन बेहद अक्षम हो सकता है (यानी यदि आपने एक समय में 4100 बाइट्स पढ़ने के लिए अपने बफर को कॉन्फ़िगर किया है, तो प्रत्येक पढ़ने के लिए फ़ाइल सिस्टम द्वारा 2 ब्लॉक पढ़ने की आवश्यकता होगी)। यदि ब्लॉक पहले से ही कैश में हैं, तो आप RAM -> L3/L2 कैश विलंबता की कीमत का भुगतान करना बंद कर देते हैं। यदि आप दुर्भाग्यपूर्ण हैं और ब्लॉक अभी तक कैश में नहीं हैं, तो आप डिस्क-> रैम विलंबता की कीमत भी भुगतान करते हैं।

यही कारण है कि आप अधिकांश बफर को 2 की शक्ति के रूप में आकार देते हैं, और आम तौर पर डिस्क ब्लॉक आकार (या बराबर) से बड़े होते हैं। इसका मतलब है कि आपकी स्ट्रीम में से एक पढ़ने के परिणामस्वरूप कई डिस्क ब्लॉक पढ़ सकते हैं - लेकिन जो पढ़ते हैं वे हमेशा एक पूर्ण ब्लॉक का उपयोग करेंगे - कोई बर्बाद नहीं पढ़ता है।

अब, यह एक सामान्य स्ट्रीमिंग परिदृश्य में काफी हद तक ऑफसेट है क्योंकि डिस्क से पढ़ा गया ब्लॉक अभी भी स्मृति में हो रहा है जब आप अगले पढ़ने को दबाते हैं (हम यहां अनुक्रमिक पढ़ रहे हैं, सब के बाद) - तो आप अगले पढ़ने पर रैम -> एल 3/एल 2 कैश विलंबता मूल्य का भुगतान करना बंद कर देते हैं, लेकिन डिस्क-> रैम विलंबता नहीं। परिमाण के क्रम के मामले में, डिस्क-> रैम विलंबता इतनी धीमी है कि यह किसी भी अन्य विलंबता से बहुत अधिक दलदल हो सकती है जिसके साथ आप काम कर रहे हैं।

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

एक टन शर्तों और अपवादों यहाँ की रहे हैं (सिर्फ L3 पर एक संभाल रही -> L2 कैश स्थानान्तरण मन bogglingly जटिल, है और यह हर सीपीयू प्रकार के साथ बदलता है) ।

इससे 'वास्तविक दुनिया' का जवाब मिलता है: यदि आपका ऐप 99% की तरह है, तो कैश आकार को 8192 पर सेट करें और आगे बढ़ें (यहां तक ​​कि बेहतर, प्रदर्शन पर encapsulation चुनें और विवरण छिपाने के लिए BufferedInputStream का उपयोग करें)। यदि आप 1% ऐप्स में हैं जो डिस्क थ्रूपुट पर अत्यधिक निर्भर हैं, तो अपने कार्यान्वयन को तैयार करें ताकि आप विभिन्न डिस्क इंटरैक्शन रणनीतियों को स्वैप कर सकें और अपने उपयोगकर्ताओं को परीक्षण और अनुकूलित करने की अनुमति देने के लिए knobs और डायल प्रदान कर सकें (या कुछ के साथ आना स्वयं अनुकूलन प्रणाली)।

13

हाँ, यह शायद विभिन्न चीजों पर निर्भर है - लेकिन मैं संदेह है कि यह बहुत अंतर करेगा। मैं स्मृति उपयोग और प्रदर्शन के बीच एक अच्छी संतुलन के रूप में 16 के या 32 के लिए चुनने के लिए चुनते हैं।

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

+0

मैंने इस प्रयास को ..catch के बारे में संपादित किया। मेरे असली कोड में मेरे पास एक है, लेकिन मैंने पोस्ट को कम करने के लिए इसे छोड़ दिया। – ARKBAN

4

आदर्श मामले में हमारे पास एक पठन ऑपरेशन में फ़ाइल को पढ़ने के लिए पर्याप्त स्मृति होनी चाहिए। यह सबसे अच्छा कलाकार होगा क्योंकि हम सिस्टम को फाइल सिस्टम, आवंटन इकाइयों और एचडीडी को इच्छानुसार प्रबंधित करने देते हैं। प्रैक्टिस में आप पहले से ही फ़ाइल आकारों को जानकर भाग्यशाली हैं, केवल 4K तक के औसत फ़ाइल आकार का उपयोग करें (एनटीएफएस पर डिफ़ॉल्ट आवंटन इकाई)। और सबसे अच्छा: एकाधिक विकल्पों का परीक्षण करने के लिए बेंचमार्क बनाएं।

3

आप बुफर्डस्ट्रीम/पाठकों का उपयोग कर सकते हैं और फिर अपने बफर आकारों का उपयोग कर सकते हैं।

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

0

एक शॉट में अधिकांश फ़ाइलों को पढ़ने के लिए बफर को काफी बड़ा बनाएं। अलग-अलग फ़ाइलों को पढ़ने के लिए एक ही बफर और उसी संदेशडिग का पुन: उपयोग करना सुनिश्चित करें।

प्रश्न से संबंधित नहीं: सूर्य के कोड सम्मेलनों को पढ़ें, खासकर माता-पिता के आस-पास घूमना और अनावश्यक घुंघराले ब्रेसिज़ का उपयोग करना। एक while या if बयान

+0

हालांकि एक सामान्य स्थिति में साइड इफेक्ट्स से बचने के लिए आम तौर पर एक अच्छा विचार है, जबकि स्ट्रीम (या इसी तरह) से पढ़ने के दौरान राउंड लूपिंग * ऐसा * एक सामान्य मामला है जो मुझे लगता है कि इसके लिए अपवाद बनाने के लिए यह समझ में आता है। –

+0

जैसा कि मैंने टिप्पणी में कहा था, कोड को पोस्ट के प्रयोजनों के लिए संपीड़ित किया गया है। – ARKBAN

+0

सूर्य के कोडिंग सम्मेलन '' '' बयानों में '=' की सदस्यता नहीं लेते हैं। ओपी का लूप एक मानक मुहावरे है। – EJP

7

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

1

जैसा कि पहले से ही अन्य उत्तरों में उल्लिखित है, BufferedInputStreams का उपयोग करें।

उसके बाद, मुझे लगता है कि बफर आकार वास्तव में कोई फर्क नहीं पड़ता। या तो कार्यक्रम I/O बाध्य है, और बीआईएस डिफ़ॉल्ट पर बढ़ते बफर आकार, प्रदर्शन पर कोई बड़ा प्रभाव नहीं पड़ेगा।

या प्रोग्राम MessageDigest.update() के अंदर सीपीयू बाध्य है, और अधिकांश समय एप्लिकेशन कोड में नहीं बिताया जाता है, इसलिए इसे ट्वीव करने से यह मदद नहीं करेगा।

(हम्म ... कई कोर के साथ, धागे मदद कर सकता है।)

4

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

0

1024 विभिन्न प्रकार की परिस्थितियों के लिए उपयुक्त है, हालांकि अभ्यास में आप बड़े या छोटे बफर आकार के साथ बेहतर प्रदर्शन देख सकते हैं।

यह फ़ाइल सिस्टम ब्लॉक आकार और सीपीयू हार्डवेयर सहित कई कारकों पर निर्भर करेगा।

यह आम, बफर आकार के लिए 2 के एक शक्ति का चयन करने के बाद से सबसे अंतर्निहित हार्डवेयर fle ब्लॉक और संचय आकारों कि 2. की एक शक्ति बफर कक्षाएं आप बफर आकार निर्दिष्ट करने के लिए अनुमति देते हैं के साथ संरचित है निर्माता में। यदि कोई भी प्रदान नहीं किया जाता है, तो वे डिफ़ॉल्ट मान का उपयोग करते हैं, जो अधिकांश JVMs में 2 की शक्ति है।

चाहे आप कौन से बफर आकार का चयन करते हैं, भले ही आप सबसे बड़ा प्रदर्शन बढ़ाएंगे देखें buffered फ़ाइल पहुंच में nonbuffered से चल रहा है। बफर आकार को समायोजित करने से प्रदर्शन में थोड़ा सुधार हो सकता है, लेकिन जब तक कि आप बेहद छोटे या अत्यधिक बड़े बफर आकार का उपयोग नहीं कर रहे हैं, तो यह संकेतक प्रभाव होने की संभावना नहीं है।

0

BufferedInputStream के स्रोत में आप पाएंगे: निजी स्थैतिक int DEFAULT_BUFFER_SIZE = 8192;
तो यह आपके लिए उस डिफ़ॉल्ट मान का उपयोग करने के लिए ओकी है।
लेकिन यदि आप कुछ और जानकारी प्राप्त कर सकते हैं तो आपको अधिक मूल्यवान उत्तर मिलेंगे।
उदाहरण के लिए, आपका adsl शायद 1454 बाइट्स का बफर प्रीफर कर सकता है, क्योंकि टीसीपी/आईपी का पेलोड। डिस्क के लिए, आप उस मान का उपयोग कर सकते हैं जो आपकी डिस्क के ब्लॉक आकार से मेल खाता है।

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