2011-01-18 22 views
8

मैं वर्तमान में JOGL (जावा ओपनजीएल बाइंडिंग) का उपयोग कर 3 डी ग्राफिक्स एप्लिकेशन विकसित कर रहा हूं। संक्षेप में, मेरे पास एक विशाल परिदृश्य बाइनरी फ़ाइल है। इसके आकार के कारण, मुझे रन-टाइम में इलाके के टुकड़ों को स्ट्रीम करना होगा। इसलिए, हम स्पष्ट रूप से यादृच्छिक पहुंच चिंता देखते हैं। मैं पहले से ही पहली (और गंदा :)) कार्यान्वयन समाप्त कर दिया है (शायद यह है मल्टी-थ्रेडेड), जहां मैं एक मूर्ख दृष्टिकोण का उपयोग कर रहा है ... यहाँ यह आरंभीकरण है:जावा में फ़ाइल स्ट्रीमिंग

dataInputStream = new DataInputStream(new BufferedInputStream(fileInputStream,4 * 1024); 
dataInputStream.mark(dataInputStream.available()); 

और जब मैं

dataInputStream.reset(); 
dataInputStream.skipBytes(offset); 
dataInputStream.read(whatever I need...); 

जब से मैं छोटा सा अनुभव है कि पहले था: (धारा) विशेष हिस्सा (मैं पहले से ही पता है अपने "ऑफसेट" फ़ाइल में) मैं निम्नलिखित प्रदर्शन कर रहा हूँ (मुझ पर शर्म की बात है :)) पढ़ने की जरूरत है चीज मैं सोच सकता था :) तो, अब तक मैंने 3 उपयोगी और काफी रोचक लेख पढ़े हैं (मैं आपको उन्हें पढ़ने के लिए सुझाव दे रहा हूं, शायद यदि आप इस विषय में रुचि रखते हैं)

  1. Byte Buffers and Non-Heap Memory - श्री ग्रेगरी जावा NIO में साक्षर हो रहा है।

  2. जावा टिप: कैसे फ़ाइलों को पढ़ने में जल्दी से [http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly] - यही कारण है कि एक दिलचस्प बेंचमार्क है।

  3. आलेख: ट्यूनिंग जावा आई/ओ प्रदर्शन [http://java.sun.com/developer/technicalArticles/Programming/PerfTuning/] - सरल सूर्य सिफारिशों, लेकिन नीचे स्क्रॉल करें और पर एक नजर है कृपया " रैंडम एक्सेस "अनुभाग वहां; वे स्वयं-बफरिंग सुधार के साथ RandomAccessFile (RAF) का एक सरल कार्यान्वयन दिखाते हैं।

श्री ग्रेगरी अपने लेख के अंत में कई * .java फाइलें प्रदान करता है। उनमें से एक फाइलचैनेल + बाइटबफर + मैपिंग (एफबीएम) और आरएएफ के बीच बेंचमार्किंग है। उनका कहना है कि उन्होंने आरएएफ की तुलना में एफबीएम का उपयोग करते समय 4x गतिरोध देखा। (, फ़ाइल दायरे में ई जी 0 - file.length()।।)

  1. ऑफसेट बेतरतीब ढंग से उत्पन्न होता है;: मैं निम्न स्थितियों में इस बेंचमार्क भाग गया है (ई जी पहुँच के स्थान पर।।)
  2. फ़ाइल का आकार 220 एमबी है;
  3. 1 000 000 पहुंच (75% पढ़ता है और 25% राईट)

परिणाम आश्चर्यजनक थे: आरएएफ के लिए

~ 28 सेकंड! ~ एफबीएम के लिए 0.2 सेकंड!

हालांकि, इस बेंचमार्क में आरएएफ के बारे में उनकी कार्यान्वयन स्वयं बफरिंग (3 लेख के बारे में एक कहता है) नहीं है, तो मैं इसे "RandomAccessFile.seek" विधि फोन, जो प्रदर्शन चला जाता है बहुत मुश्किल है लगता है।

ठीक है, अब उन सभी चीजें मैं वहाँ 1 प्रश्न और 1 दुविधा :)

प्रश्न है सीखा है के बाद: हम का उपयोग कर "FileChannel.map" जावा कॉपी करता है पूरी फ़ाइल एक फ़ाइल मानचित्रण कर रहे हैं MappedByteBuffer में सामग्री? या यह सिर्फ इसे अनुकरण करता है?यदि यह प्रतिलिपि बनाता है, तो एफबीएम दृष्टिकोण का उपयोग मेरी स्थिति के लिए उपयुक्त नहीं है, है ना?

दुविधा: प्रश्न पर अपने जवाब पर निर्भर करता है ...

  1. मानचित्रण प्रतियां एक फ़ाइल है, तो ऐसा लगता है जैसे मैं जाने के लिए केवल 2 संभव समाधान है: आरएएफ + आत्म बफरिंग (तीसरे आलेख में से एक) या फ़ाइलChannel (मैपिंग के साथ नहीं) में स्थिति का उपयोग करें ... कौन सा बेहतर होगा?

  2. यदि मानचित्रण फ़ाइल की प्रतिलिपि नहीं करता है, तो मेरे पास 3 विकल्प हैं: दो पिछले और एफबीएम स्वयं

संपादित: यहाँ एक और सवाल है। आप में से कुछ यहां कहते हैं कि मैपिंग फ़ाइल को मैप्डबेट बफर में कॉपी नहीं करता है। ठीक है तो, मैं क्यों 1GB फ़ाइल तो मैप कर सकते हैं नहीं, मैं हो रही है संदेश "को नहीं ढूंढ़ सकी" ...

पुनश्च मैं सलाह के साथ एक पूरा जवाब प्राप्त करना चाहते हैं, के बाद से मैं नहीं पा रहा हूँ इंटरनेट पर इस विषय पर लगातार जानकारी खोजने के लिए।

धन्यवाद :)

उत्तर

3

नहीं, डेटा buffered नहीं है। एक मैप्डबेट बफर pointer का उपयोग कर डेटा का संदर्भ देता है। दूसरे शब्दों में, डेटा की प्रतिलिपि नहीं बनाई गई है, यह मैप भौतिक स्मृति में मैप किया गया है। यदि आप पहले से नहीं हैं तो API docs देखें।

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

स्रोत: Wikipedia

आप अक्सर डाटा पढ़ने के लिए जा रहे हैं, तो यह एक अच्छा विचार कम से कम इसके बारे में कुछ कैश करने के लिए है।

+0

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

+0

@ हरोगोगन मैं उस लेख से उद्धरण देता हूं: "अंतर लगभग पूरी तरह से कर्नेल संदर्भ स्विच के कारण है" – someguy

+0

आपको जवाडोक का जिक्र करके आपको मजाक करना होगा, है ना? Coz, मैं कोई विशेष जानकारी नहीं मांग रहा हूँ। मुझे अभी भी संभावित समाधानों पर कोई प्रत्यक्ष उत्तर या उचित विचार और टिप्पणियां नहीं मिली हैं। –

2

एक 220 एमबी फ़ाइल मैं स्मृति आभासी स्मृति में पूरी बात को मैप होगा के लिए। कारण FBM इतना तेज़ है कि यह वास्तव में डेटा को स्मृति में नहीं पढ़ता है, यह केवल इसे उपलब्ध कराता है।

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

+0

"उपलब्ध" से आपका क्या मतलब है? केवल 2 विकल्प हो सकते हैं: फ़ाइल पूरी तरह से मैप्डबेटबफर (अधिकतम आकार 32-बिट सिस्टम के लिए 2 जीबी है) पर मैप किया गया है या मैप्डबेटबफर सिर्फ पृष्ठभूमि बफरिंग का उपयोग करके इस फ़ाइल को अनुकरण करता है, तर्क या भविष्यवाणी की भविष्यवाणी करता है ... चूंकि मैंने 1 जीबी मैप करने की कोशिश की है फ़ाइल और ऐसा करने में असफल रहा, मुझे यह निष्कर्ष निकालना है कि इसकी मैपिंग पूरी फ़ाइल को मैप्डबेट बफर में कॉपी करने लगती है ... या क्या मैं अभी भी गलत हूं? कृपया अपने उत्तरों में अधिक विस्तृत जानकारी प्राप्त करें। –

+0

मैपिंग करते समय, ओएस फ़ाइल को वर्चुअल मेमोरी में मैप करता है। फ़ाइल के पृष्ठ (आमतौर पर 4 केबी) को स्मृति में लाया जाता है जब आप उन्हें पढ़ते/लिखते हैं और धीरे-धीरे डिस्क पर फ्लश कर रहे हैं। (या जब आप फ्लश को मजबूर करते हैं) 0.2 सेकंड में स्मृति में 220 एमबी फ़ाइल को पढ़ने में कोई तरीका नहीं है। मुझे यकीन नहीं है कि जब तक आप 32-बिट JVM का उपयोग नहीं कर रहे हैं तब तक 1 जीबी फ़ाइल मैप होने में विफल रही। –

+0

हाँ, मैं 32-बिट जेवीएम का उपयोग कर रहा हूं, इसलिए मुझे समझ में नहीं आता कि 1 जीबी फ़ाइल मैपिंग क्यों विफल हो जाती है ... कोई विचार? वर्तमान में मुझे केवल पढ़ने में रूचि है, इसलिए मुझे फ्लश और इत्यादि की आवश्यकता नहीं है। आपने अभी कहा है कि ओएस वर्चुअल मेमोरी में 4 केबी पेज लोड कर रहा है, लेकिन आप देखते हैं कि मैंने पहले क्या कहा है, i। ई। मैप्डबेटबफर बस धीमी पृष्ठभूमि बफरिंग तर्क का उपयोग करके इस फ़ाइल को अनुकरण करता है, जिसे मैं नियंत्रित नहीं कर सकता। सही? –

1

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

संपादित करें: आप क्या चाहते हैं FileInputStream.getChannel()। नक्शा(), फिर इनपुट इनपुट में इसे अनुकूलित करें, फिर उसे DataInputStream से कनेक्ट करें।

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