2012-06-24 8 views
8

मैं 50 जी फ़ाइल पढ़ रहा हूं जिसमें लाखों पंक्तियां न्यूलाइन कैरेक्टर से अलग हैं। वर्तमान में मैं निम्नलिखित वाक्य रचना का उपयोग कर रहा फ़ाइलजावा 50 गीगाबिट फ़ाइल पढ़ने में सुधार कैसे करें

String line = null; 
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("FileName"))); 
while ((line = br.readLine()) != null) 
{ 
// Processing each line here 
// All processing is done in memory. No IO required here. 
} 

पढ़ने के लिए के बाद से फ़ाइल बहुत बड़ी है, यह 2 बजे ले जा रहा है पूरी फ़ाइल पर कार्रवाई करने। क्या मैं हार्डडिस्क से फ़ाइल को पढ़ने में सुधार कर सकता हूं ताकि आईओ (पठन) ऑपरेशन में न्यूनतम समय लगे। मेरे कोड के साथ प्रतिबंध यह है कि मुझे प्रत्येक पंक्ति अनुक्रमिक क्रम को संसाधित करना होगा।

+0

जावा के 'BufferedReader' के कार्यान्वयन क्या है के माध्यम से पढ़ने के लिए ले जाता है हो सकता है? शायद आप अलग-अलग थ्रेड में ब्लॉक (ऑपरेटिंग सिस्टम और फ़ाइल सिस्टम को इष्टतम आकार के साथ) पढ़ने के द्वारा वहां सुधार कर सकते हैं। –

+8

क्या आपका मतलब 50 जीबीटी या 50 गीबी है? –

उत्तर

8

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

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

मैं हडोप और एक वितरित समाधान के बारे में सोचता हूं। आपके द्वारा बड़े डेटा सेट नियमित रूप से संसाधित होते हैं। आपको अपनी सोच में थोड़ा अधिक रचनात्मक होने की आवश्यकता हो सकती है।

+0

नोट किया गया - मैंने अपना जवाब दोबारा संशोधित किया। – duffymo

10

पूरी फ़ाइल को संसाधित करने में 2 घंटे लग रहे हैं।

50 जीबी/2 घंटे लगभग 7 एमबी/एस बराबर है। यह बिल्कुल खराब दर नहीं है। एक अच्छी (आधुनिक) हार्ड डिस्क लगातार उच्च दर को बनाए रखने में सक्षम होना चाहिए, तो शायद आपकी बाधा आई/ओ नहीं है? आप पहले से ही BufferedReader का उपयोग कर रहे हैं, जो नाम कहता है, बफरिंग (मेमोरी में) जो इसे पढ़ता है। आप डिफ़ॉल्ट आकार (8192 बाइट्स) की तुलना में थोड़ा बड़ा बफर के साथ पाठक बनाने प्रयोग कर सका, इसलिए जैसे:

BufferedReader br = new BufferedReader(
    new InputStreamReader(new FileInputStream("FileName")), 100000); 

ध्यान दें कि डिफ़ॉल्ट के साथ 8192 बाइट्स बफ़र और 7 MB/s throughput BufferedReader फिर जा रहा है - अपने बफर को प्रति सेकेंड लगभग 1000 गुना भरें, इसलिए उस नंबर को कम करने से वास्तव में कुछ ओवरहेड को कम करने में मदद मिल सकती है। लेकिन अगर आप जो प्रोसेसिंग कर रहे हैं, I/O की बजाय बाधा है, तो कोई I/O चाल आपको बहुत मदद करने जा रही है। आपको शायद इसे बहु-थ्रेडेड बनाने पर विचार करना चाहिए, लेकिन क्या यह करने योग्य है, और कैसे, "प्रसंस्करण" का अर्थ यहां निर्भर करता है।

+2

7 एमबी/एस निरंतर रैखिक डिस्क I/O के लिए भयानक है ... –

+1

हां, आज सामान्य दर बेंचमार्क * में परिमाण उच्च * का क्रम है। हालांकि, डिस्क आरपीएम, विखंडन इत्यादि - और विशेष रूप से अन्य प्रोग्राम और ओएस पृष्ठभूमि में अपनी खुद की चीजें कर रहे हैं - इसका असर असर पड़ता है। 5 एमबी/एस के लिए 10 एमबी/एस एक वास्तविक वास्तविक दुनिया संख्या नहीं है। –

+3

मुझे लगता है कि आप सही हैं। मुझे लगता है कि मैं उन डिस्क के बारे में सोचने के लिए प्रयोग करता हूं जिन्हें मैं काम पर उपयोग करता हूं, जहां 100 एमबी/एस निरंतर (अभ्यास में) सामान्य है। –

5

एनआईओ के बिना आप थ्रूपुट बाधा को तोड़ने में सक्षम नहीं होंगे। उदाहरण के लिए, सीधे पाठकों को बनाने के बजाय new Scanner(File) का उपयोग करने का प्रयास करें। हाल ही में मैंने उस स्रोत कोड पर एक नज़र डाली, यह एनआईओ के फाइल चैनलों का उपयोग करता है।

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

+0

स्कैनर हेप बफर का उपयोग करता है, सीधे बफर मैप नहीं किया जाता है। तो यह FileInputStream.read से बहुत अलग नहीं है (अभी भी बेहतर है क्योंकि बफर होने पर प्रत्येक पढ़ने पर मॉलोक/फ्री की आवश्यकता नहीं होती है> 8 केबी) – bestsss

2
  1. एंटीवायरस और किसी अन्य प्रोग्राम को अक्षम करें जो फ़ाइल पढ़ने के दौरान डिस्क विवाद में जोड़ता है।

  2. डिस्क को डिफ्रैगमेंट करें।

  3. कच्चे डिस्क विभाजन बनाएं और वहां से फ़ाइल पढ़ें।

  4. एक एसएसडी से फ़ाइल पढ़ें।

  5. 50 जीबी रामडिस्क बनाएं और वहां से फ़ाइल पढ़ें।

1

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

0

जिस तरह से आप फ़ाइल पढ़ते हैं ठीक है। इसे तेजी से प्राप्त करने के तरीके हो सकते हैं, लेकिन आमतौर पर यह समझने की आवश्यकता होती है कि आपकी बाधा कहाँ है। चूंकि आईओ थ्रूपुट वास्तव में निचले सिरे पर है, मुझे लगता है कि गणना में प्रदर्शन पक्ष प्रभाव पड़ रहा है। यदि यह बहुत लंबा नहीं है तो आप पूरे कार्यक्रम को दिखा सकते हैं।

वैकल्पिक रूप से, आप पाश की सामग्री को बिना अपने कार्यक्रम चलाने और देखो कितनी देर तक यह फ़ाइल :)

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