2009-06-21 17 views
8

मैं कुछ बहुत तेज़ जावा कोड लिखने की कोशिश कर रहा हूं जिसे बहुत सारे I/O करना है। मैं एक स्मृति मैप की गई फ़ाइल है कि एक ByteBuffer रिटर्न उपयोग कर रहा हूँ:जावा में मेमोरी-मैप की गई फ़ाइलें

public static ByteBuffer byteBufferForFile(String fname){ 
    FileChannel vectorChannel; 
    ByteBuffer vector; 
    try { 
     vectorChannel = new FileInputStream(fname).getChannel(); 
    } catch (FileNotFoundException e1) { 
     e1.printStackTrace(); 
     return null; 
    } 
    try { 
     vector = vectorChannel.map(MapMode.READ_ONLY,0,vectorChannel.size()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
    return vector; 
} 

समस्या यह है कि मैं आ रही हैं कि ByteBuffer .array() विधि (जो एक बाइट [] सरणी लौटना चाहिए) काम नहीं करता है केवल पढ़ने के लिए फाइलों के लिए। मैं अपना कोड लिखना चाहता हूं ताकि यह डिस्क से पढ़ने वाली मेमोरी और बफर में निर्मित मेमोरी बफर दोनों के साथ काम करेगा। लेकिन मैं अपने सभी बफर को एक ByteBuffer.wrap() फ़ंक्शन को लपेटना नहीं चाहता क्योंकि मुझे चिंता है कि यह चीजों को धीमा कर देगा। तो मैं सब कुछ के दो संस्करण लिख रहा हूं, एक बाइट [] लेता है, दूसरा जो बाइटबफर लेता है।

क्या मुझे बस सबकुछ लपेटना चाहिए? या मुझे सबकुछ दोबारा लिखना चाहिए?

+3

बेंचमार्क और परिणाम पोस्ट करें, भले ही एक विशेषज्ञ आपको एक दिशा में इंगित कर सके कि दिशा आपकी स्थिति के लिए काम नहीं कर सकती है। बेंचमार्क!!!! – basszero

उत्तर

10

क्या कोई वास्तव में यह देखने के लिए जांच करता है कि ByteBuffers मेमोरी मैपिंग समर्थन द्वारा निर्मित .array() को पहले स्थान पर रीडोनली/रीडराइट की परवाह किए बिना?

जहां तक ​​मैं कह सकता हूं, मेरे पोकिंग से, उत्तर NO है। एक ByteBuffer के माध्यम से सीधे byte[] सरणी वापस करने की क्षमता ByteBuffer.hb (byte[]) की उपस्थिति से गुज़रती है, जो MappedByteBuffer बनने पर हमेशा शून्य हो जाती है।

किस तरह से मेरे लिए बेकार है, क्योंकि मैं ऐसा कुछ करने की उम्मीद कर रहा था जो प्रश्न लेखक करना चाहता था।

+0

मैं सहमत हूं। यह बेकार है। मुझे विश्वास नहीं है कि बाइटबफर सरणी() को लागू नहीं करता है। दूसरी ओर, हमने कुछ प्रदर्शन परीक्षण किए, और हमने पाया कि प्रोग्रामिंग-आईओ का उपयोग करने के बजाय स्मृति-मैप की गई फ़ाइल के साथ .get() का उपयोग करना कभी-कभी तेज़ होता है, और कभी-कभी प्रोग्राम किए गए io का उपयोग करने के लिए तेज़ होता है। यह बहुत अजीब है। लेकिन स्मृति-मैप की गई फ़ाइलों की तुलना में प्रोग्राम किए गए io पर अधिक भिन्नता है। – vy32

+3

एक 'बाइट []' ढेर पर होना चाहिए। मेमोरी के मेमोरी मैप किए गए ब्लॉक को ढेर के बाहर होना चाहिए। भेदभाव पारदर्शी होने पर अच्छा होगा, लेकिन मैं बाइटबफर के गेटलॉन्ग/पॉटलांग विधि का उपयोग करना पसंद करता हूं (ये मूल क्रम का उपयोग करने के साथ बहुत तेज हैं) –

1

ByteBuffer.wrap() कार्यक्षमता का उपयोग करना एक उच्च बोझ नहीं लगाता है। यह एक साधारण वस्तु आवंटित करता है और कुछ पूर्णांक प्रारंभ करता है। बाइटबफर के खिलाफ अपना एल्गोरिदम लिखना इस प्रकार आपकी सबसे अच्छी शर्त है यदि आपको केवल पढ़ने वाली फ़ाइलों के साथ काम करने की आवश्यकता है।

4

लपेटना बाइट [] चीजों को धीमा नहीं करेगा ... कोई बड़ी सरणी प्रतियां या अन्य छोटी प्रदर्शन बुराई नहीं होगी। जावा डॉक्स से: java.nio.ByteBuffer .wrap()

एक बफर में एक बाइट सरणी लपेटता है।

नए बफर को दिए गए बाइट सरणी द्वारा समर्थित किया जाएगा; है, बफर में संशोधन संशोधित करने के लिए सरणी और उपाध्यक्ष बनाम होगा। नई बफर की क्षमता और सीमा सरणी होगी। लम्बाई, इसकी स्थिति शून्य होगी, और इसका निशान अपरिभाषित होगा। इसकी बैकिंग सरणी दी गई सरणी होगी, और इसकी सरणी ऑफसेट शून्य होगी।

+0

धन्यवाद। मैं बस [i] के बजाय .get (i) के साथ हर बाइट को पढ़ने के बारे में चिंतित हूं, क्योंकि .get (i) में एक विधि कॉल शामिल है जबकि [i] बाइटकोड में किया जाता है। – vy32

+4

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

+0

असल में, मैं कंप्यूटर फोरेंसिक कर रहा हूं, जानकारी के टेराबाइट प्रोसेसिंग कर रहा हूं। आज तक मेरे अनुभव में जेवीएम ने जितना उम्मीद की उतनी अनुकूलित नहीं की है। – vy32

5

पहियों को फिर से शुरू करना हमेशा अच्छा नहीं होता है। अपाचे ने आई/ओ संचालन करने के लिए एक सुंदर पुस्तकालय प्रदान किया है। http://commons.apache.org/io/description.html

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

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

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

संपादित करें: मैंने अभी Google का उपयोग करके एक छोटी सी खोज की है और यह लिंक पाया है: http://lists.apple.com/archives/java-dev/2004/Apr/msg00086.html (लाइटनिंग फास्ट फ़ाइल पढ़ने/लिखना)। बहुत प्रभावशाली।

+0

यदि मैं गलत हूं तो मुझे सही करें। आप I/O संचालन करने का तेज़ तरीका ढूंढ रहे हैं। सही बात?? –

+0

असल में, मैं बस मुझे करने के तेज़ तरीकों की तलाश में हूं, लेकिन मैं न्यूनतम बफर प्रतियों के साथ बफर को संसाधित करने के तरीकों की भी तलाश कर रहा हूं। – vy32

+0

@ गौरवसेनी: क्या आप अपाचे कॉमन्स-io से 'DeferredOutputStream' का उल्लेख करते हैं? मुझे javadoc में v2.3 और v2.2 के लिए ऐसी कक्षा नहीं मिल रही है। –

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