2011-05-22 14 views
7

बढ़ाने के लिए मैं फ़ाइलों पर चेकसम गणना करने के लिए निम्नलिखित समारोह का उपयोग कर रहा जरूरत:जावा: चेकसम गणना के प्रदर्शन

public static void generateChecksums(String strInputFile, String strCSVFile) { 
    ArrayList<String[]> outputList = new ArrayList<String[]>(); 
    try { 
     MessageDigest m = MessageDigest.getInstance("MD5"); 
     File aFile = new File(strInputFile); 
     InputStream is = new FileInputStream(aFile); 

     System.out.println(Calendar.getInstance().getTime().toString() + 
        " Processing Checksum: " + strInputFile); 

     double dLength = aFile.length(); 
     try { 
      is = new DigestInputStream(is, m); 
      // read stream to EOF as normal... 
      int nTmp; 
      double dCount = 0; 
      String returned_content=""; 
      while ((nTmp = is.read()) != -1) { 
       dCount++; 
       if (dCount % 600000000 == 0) { 
        System.out.println(". "); 
       } else if (dCount % 20000000 == 0) { 
        System.out.print(". "); 
       } 
      } 
      System.out.println(); 
     } finally { 
      is.close(); 
     } 
     byte[] digest = m.digest(); 
     m.reset(); 
     BigInteger bigInt = new BigInteger(1,digest); 
     String hashtext = bigInt.toString(16); 
     // Now we need to zero pad it if you actually/want the full 32 chars. 
     while(hashtext.length() < 32){ 
      hashtext = "0" + hashtext; 
     } 
     String[] arrayTmp = new String[2]; 
     arrayTmp[0] = aFile.getName(); 
     arrayTmp[1] = hashtext; 
     outputList.add(arrayTmp); 
     System.out.println("Hash Code: " + hashtext); 
     UtilityFunctions.createCSV(outputList, strCSVFile, true); 
    } catch (NoSuchAlgorithmException nsae) { 
     System.out.println(nsae.getMessage()); 
    } catch (FileNotFoundException fnfe) { 
     System.out.println(fnfe.getMessage()); 
    } catch (IOException ioe) { 
     System.out.println(ioe.getMessage()); 
    } 
} 

समस्या यह है कि पाश फ़ाइल में पढ़ने के लिए वास्तव में धीमी है:

while ((nTmp = is.read()) != -1) { 
    dCount++; 
    if (dCount % 600000000 == 0) { 
     System.out.println(". "); 
    } else if (dCount % 20000000 == 0) { 
     System.out.print(". "); 
    } 
} 

एक 3 जीबी फ़ाइल जो एक स्थान से दूसरे स्थान पर प्रतिलिपि बनाने के लिए एक मिनट से भी कम समय लेती है, गणना करने के लिए एक घंटे लगती है। क्या ऐसा कुछ है जो मैं इसे तेज करने के लिए कर सकता हूं या क्या मुझे शेल कमांड का उपयोग करने जैसी अलग दिशा में जाने की कोशिश करनी चाहिए?

अद्यतन: धन्यवाद सनकी के सुझाव मैं यह जो हास्यास्पद तेजी से होता है करने के लिए कोड बदल शाफ़्ट (मैं 2048x तेजी से लगता है कि होगा ...): एक बफर

byte[] buff = new byte[2048]; 
while ((nTmp = is.read(buff)) != -1) { 
    dCount += 2048; 
    if (dCount % 614400000 == 0) { 
     System.out.println(". "); 
    } else if (dCount % 20480000 == 0) { 
     System.out.print(". "); 
    } 
} 
+0

विचार बाहर मानक के प्रगति को बताता है खोजने की कोशिश करें। यह कमांड लाइन ftp क्लाइंट के "हैश" व्यवहार को अनुकरण करने का मेरा तरीका था। Dcount% 60000000 एक प्रिंट बनाम एक प्रिंट बनाम करता है। – opike

उत्तर

4

का उपयोग

byte[] buff = new byte[2048]; 
while ((nTmp = is.read(buff)) != -1) 
{ 
    dCount+=ntmp; 
    //this logic won't work anymore though 
    /* 
    if (dCount % 600000000 == 0) 
    { 
     System.out.println(". "); 
    } 
    else if (dCount % 20000000 == 0) 
    { 
     System.out.print(". "); 
    } 
    */ 
} 

संपादित करें: या यदि आप की जरूरत नहीं है मान कर

while(is.read(buff)!=-1)is.skip(600000000); 

nvm जाहिरा तौर पर DigestInputStream के कार्यान्वयन बेवकूफ थे और रिहाई

+0

'DigestInputStream'' skip() 'को ओवरराइड नहीं करता है, इसलिए छोड़े गए बाइट्स को डायजेस्टर द्वारा संसाधित नहीं किया जाएगा। – McDowell

+1

स्पष्ट रूप से आपने DigestInputStream के लिए जावाडोक नहीं पढ़ा, जहां यह * नहीं कहता है कि डाइजेस्ट अद्यतन को छोड़ दें। बेवकूफ टिप्पणी के लिए downvoted। – EJP

+0

दोस्त यह छोड़ने के बारे में _anything_ नहीं कहता है और वे निर्माण पर पचाने पर नलपोइंटर की भी जांच नहीं करते हैं, यह पता लगाने के लिए कि आप कहीं और एक लपेटी हुई धारा पर एनपीई क्यों प्राप्त करते हैं –

2

आप println के दूर करने की कोशिश की है से पहले ठीक से सब कुछ का परीक्षण नहीं किया? मुझे लगता है कि सभी स्ट्रिंग मैनिप्ल्यूशन अधिकांश प्रोसेसिंग का उपभोग कर सकता है!

संपादित करें: मैं, स्पष्ट रूप से इसे पढ़ा नहीं था अब मुझे पता है कि कैसे कभी-कभी वे उत्पादन होगा, मैं अपने जवाब को वापस लेना चाहते हैं लेकिन मुझे लगता है कि यह पूरी तरह से अमूल्य :-P नहीं था

+2

println केवल समय का एक छोटा सा% होता है ... यदि कुछ भी प्रदर्शन को प्रभावित कर रहा है तो यह सशर्त तर्क है। – opike

+0

+1: कंसोल आउटपुट को ध्यान में रखते हुए। यह इस स्थिति में एकमात्र प्रदर्शन वृद्धि नहीं होगी लेकिन कई प्रोग्रामर यह नहीं समझते कि कंसोल पर लिखते समय कितना ओवरहेड होता है। यह एक आवेदन को काफी धीमा कर सकता है। –

+0

डाउनवॉटेड क्योंकि "सभी स्ट्रिंग मैनिपुलेशन" केवल बीस मिलियन पुनरावृत्तियों में एक बार हो रहा है। – QuantumMechanic

0
(क्षमा करें!)

समस्या यह है कि System.out.print का उपयोग अक्सर किया जाता है। हर बार इसे नई स्ट्रिंग ऑब्जेक्ट कहा जाता है और इसे महंगा होता है।

इसके बजाय स्ट्रिंगबिल्डर वर्ग का उपयोग करें या इसके थ्रेड सुरक्षित एनालॉग स्ट्रिंगबफर का उपयोग करें।

StringBuilder sb = new StringBuilder(); 

और हर बार आप कुछ कॉल जोड़ने की जरूरत है इस:

sb.append("text to be added"); 

बाद में, जब आप इसे प्रिंट करने के लिए तैयार हैं:

system.out.println(sb.toString()); 
0

सच कहूं वहाँ अपने कोड के साथ कई समस्याएं हैं इससे धीमा हो जाता है:

  1. रैचेट फ्रीक की तरह, डिस्क पढ़ने को बफर किया जाना चाहिए क्योंकि जावा read() का शायद ऑपरेटिंग सिस्टम आईओएस कॉल में स्वचालित रूप से बफरिंग किए बिना कॉल किया गया है, इसलिए एक read() 1 सिस्टम कॉल है !!! यदि आप बफर या BufferedInputStream के रूप में किसी सरणी का उपयोग करते हैं तो ऑपरेटिंग सिस्टम सामान्य रूप से बेहतर प्रदर्शन करेगा। बेहतर अभी तक, आप फाइल को मेमोरी में मैप करने के लिए एनओओ का उपयोग कर सकते हैं और ओएस इसे संभाल सकते हैं जितना तेज़ी से पढ़ सकते हैं।

  2. आप इसे विश्वास नहीं कर सकते हैं, लेकिन dCount++; काउंटर ने कई चक्रों का उपयोग किया होगा। मेरा मानना ​​है कि नवीनतम इंटेल कोर प्रोसेसर के लिए भी, 64-बिट फ़्लोटिंग पॉइंट एड को पूरा करने में कई घड़ी चक्र लगते हैं।आप इस काउंटर के लिए लंबे समय तक उपयोग करने के लिए बेहतर होंगे। यदि इस काउंटर का एकमात्र उद्देश्य प्रगति प्रदर्शित करना है, तो आप इस तथ्य का उपयोग कर सकते हैं कि त्रुटि के बिना जावा पूर्णांक ओवरफ़्लो हो सकता है और जब कोई चार प्रकार 0 तक गिर जाता है (जो प्रति 65536 पढ़ता है) तो आपकी प्रगति डिस्प्ले को अग्रिम करें।

  3. निम्न स्ट्रिंग पैडिंग भी अक्षम है। आपको StringBuilder या Formatter का उपयोग करना चाहिए।

    जबकि (हैशटेक्स्ट। लम्बाई() < 32) { हैशटेक्स्ट = "0" + हैशटेक्स्ट; }

  4. एक प्रोफाइलर का उपयोग कर अपने कोड में आगे दक्षता समस्याओं

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