2010-02-26 16 views
5

मैं डेटाबेस से डेटा को एक्सेल फ़ाइल में भेजने के लिए प्रोग्राम का उपयोग कर रहा हूं। यह शुरुआत में ठीक काम करता है और फिर धीरे-धीरे धीरे-धीरे हो जाता है, अंततः यह स्मृति से बाहर चला जाता है और निम्न त्रुटि ocurrs: "java.lang.OutOfMemoryError: जावा हीप स्पेस ..."।मेरा प्रोग्राम धीमा और धीमा क्यों हो रहा है?

समस्या जेवीएम ढेर sapce जोड़कर हल किया जा सकता है। लेकिन सवाल यह है कि यह कार्यक्रम चलाने के लिए बहुत अधिक समय बिताता है।

कई मिनटों के बाद, यह 4 सेकंड के साथ एक लूप समाप्त हुआ जिसे शुरुआत में 0.5 सेकंड के साथ समाप्त किया जा सकता है। मुझे हमेशा एक निश्चित गति में चलाने के लिए एक समाधान नहीं मिला है।

क्या यह मेरी कोड समस्या है?

इस पर कोई संकेत?

public void addAnswerRow(List<FinalUsers> finalUsersList,WritableWorkbook book){ 

    if (finalUsersList.size() >0) { 
    try { 
     WritableSheet sheet = book.createSheet("Answer", 0); 
     int colCount = 0; 
     sheet.addCell(new Label(colCount++,0,"Number")); 
     sheet.addCell(new Label(colCount++,0,"SchoolNumber")); 
     sheet.addCell(new Label(colCount++,0,"District")); 
     sheet.addCell(new Label(colCount++,0,"SchoolName")); 
     sheet.setColumnView(1, 15); 
     sheet.setColumnView(3, 25); 

     List<Elements> elementsList = this.elementsManager.getObjectElementsByEduTypeAndQuestionnaireType(finalUsersList.get(0).getEducationType().getId(),  this.getQuestionnaireByFinalUsersType(finalUsersList.get(0).getFinalUsersType().getId())); 

     Collections.sort(elementsList, new Comparator<Elements>(){ 

      public int compare(Elements o1, Elements o2) { 

      for(int i=0; i< (o1.getItemNO().length()>o2.getItemNO().length()? o2.getItemNO().length(): o1.getItemNO().length());i++){ 
        if (CommonFun.isNumberic(o1.getItemNO().substring(0, o1.getItemNO().length()>3? 4: o1.getItemNO().length()-1)) && !CommonFun.isNumberic(o2.getItemNO().substring(0, o2.getItemNO().length()>3? 4: o2.getItemNO().length()-1))){ 
       return 1; 
        } 
       if (!CommonFun.isNumberic(o1.getItemNO().substring(0, o1.getItemNO().length()>3? 4: o1.getItemNO().length()-1)) && CommonFun.isNumberic(o2.getItemNO().substring(0,o2.getItemNO().length()>3? 4:o2.getItemNO().length()-1))){ 
       return -1; 
       } 
       if (o1.getItemNO().charAt(i)!=o2.getItemNO().charAt(i)){ 

        return o1.getItemNO().charAt(i)-o2.getItemNO().charAt(i); 
       } 
      } 
      return o1.getItemNO().length()> o2.getItemNO().length()? 1:-1; 
     }}); 

     for (Elements elements : elementsList){ 
      sheet.addCell(new Label(colCount++,0,this.getTitlePre(finalUsersList.get(0).getFinalUsersType().getId(), finalUsersList.get(0).getEducationType().getId())+elements.getItemNO()+elements.getItem().getStem())); 
     } 

     int sheetRowCount =1; 
     int sheetColCount =0; 

     for(FinalUsers finalUsers : finalUsersList){ 

      sheetColCount =0; 

      sheet.addCell(new Label(sheetColCount++,sheetRowCount,String.valueOf(sheetRowCount))); 
      sheet.addCell(new Label(sheetColCount++,sheetRowCount,finalUsers.getSchool().getSchoolNumber())); 
      sheet.addCell(new Label(sheetColCount++,sheetRowCount,finalUsers.getSchool().getDistrict().getDistrictNumber().toString().trim())); 
      sheet.addCell(new Label(sheetColCount++,sheetRowCount,finalUsers.getSchool().getName())); 

      List<AnswerLog> answerLogList = this.answerLogManager.getAnswerLogByFinalUsers(finalUsers.getId()); 


      Map<String,String> answerMap = new HashMap<String,String>(); 

      for(AnswerLog answerLog :answerLogList){ 
      if (answerLog.getOptionsId() != null) 
      { 
       answerMap.put(answerLog.getElement().getItemNO(), this.getOptionsAnswer(answerLog.getOptionsId())); 
      }else if (answerLog.getBlanks()!= null){ 

       answerMap.put(answerLog.getElement().getItemNO(), answerLog.getBlanks()); 
      }else{ 

       answerMap.put(answerLog.getElement().getItemNO(), answerLog.getSubjectiveItemContent()); 
      } 
      } 
      for (Elements elements : elementsList){ 

      sheet.addCell(new Label(sheetColCount++,sheetRowCount,null==answerMap.get(elements.getItemNO())?"0":answerMap.get(elements.getItemNO()))); 

      } 

     sheetRowCount++; 
     } 

     book.write(); 
     book.close(); 

    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (RowsExceededException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (WriteException e) { 

     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} }

+0

आप विस्तार से समझाने के लिए उदाहरण के लिए .., "मैं दो चादरें दोनों एक आम कुंजी है ले रहा हूँ की जरूरत नहीं है (नीचे टिप्पणी से जारी) (studentId या कुछ ??) और उनसे जुड़ना "या कुछ। फिर हम डिस्क स्पेस का उपयोग करके पहले इन चादरों को सॉर्ट करने के लिए मर्ज-सॉर्ट का उपयोग करने की सलाह दे सकते हैं, और फिर आप मेमोरी के गुच्छा के बिना दोनों शीट के माध्यम से पुन: सक्रिय कर सकते हैं ... –

उत्तर

9

कहीं आप वस्तुओं बनाने और उन्हें करने के लिए पहुंच योग्य संदर्भ बनाए रखने रहे हैं:

यहाँ कोड है।

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

इसके अलावा, यह संभव है कि आप प्रत्येक कार्यपुस्तिका जैसे प्रत्येक ऑब्जेक्ट को बंद करना भूल जाएं।

+0

ऐसा लगता है कि इससे बच नहीं सकते हैं। क्योंकि यह आवश्यक है डेटाबेस से डेटा पकड़ने के लिए ऑब्जेक्ट बनाएं और उस समय जब जीसी काम अनजान हो। इसके अलावा कार्यपुस्तिका अंत में बंद है: book.close() – RedWolf

+0

कोड का पालन करना मुश्किल है ... क्या आप संक्षेप में समझा सकते हैं कि आप क्या हासिल करने की कोशिश कर रहे हैं? फिर हम यह देखने में सक्षम हो सकते हैं कि यह (एक विशाल संग्रह है) वास्तव में टाला नहीं जा सकता है (यदि यह वास्तव में टाला नहीं जा सकता है, तो आप अभी भी डिस्क का उपयोग कर सकते हैं इसलिए चिंता न करें ..) –

+0

@Zwei: आप शायद आपकी टिप्पणी को प्रश्न में ले जाना चाहें ... मुझे नहीं लगता कि रेडवॉल्फ को मेरे उत्तर के तहत अधिसूचित किया जाएगा। –

2

मुझे अत्यधिक संदेह है कि आपके कार्यक्रम पर एक स्मृति रिसाव है। स्मृति रिसाव का पता लगाने के लिए जेपीरोफाइलर या योरकिट जैसे प्रोफाइलर का प्रयोग करें। शायद आप WritableWorkbook को बंद करना भूल गए हैं?

http://jexcelapi.sourceforge.net/resources/javadocs/current/docs/jxl/write/WritableWorkbook.html

+0

कार्यपुस्तिका अंत में बंद है। मैं एक मेमोरी टेस्ट चिह्नित करने जा रहा हूं। :) – RedWolf

1

आपका आवेदन ढेर स्थान से बाहर चल रहा है, यह जीसी अंत में देने और एक OutOfMemoryError फेंकने से पहले अंतरिक्ष को पुनः प्राप्त करने की कोशिश में अधिक से अधिक समय लगेगा। मैं निम्नलिखित करने की सलाह देते:

  • जब यह स्मृति से बाहर चल रहा है JVM पहले विफल करने के लिए -XX:+UseGCOverheadLimit JVM विकल्प जोड़ने।

  • उपयोग एक स्मृति प्रोफाइलर संभव स्मृति देखने के लिए

  • लीक अगर आप किसी भी लीक नहीं मिल रहा है, बस ढेर आकार में वृद्धि।

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

[सिद्धांत: अपने addAnswerRow बार-बार बुलाया जा रहा है, तो समस्या बार-बार एक एक्सेल स्प्रेडशीट फ़ाइल है कि बड़े प्रत्येक addAnswerRow कॉल के साथ एक हो रही है खोलने से संबंधित हो सकता। यह संभव है कि प्रत्येक बार जब आप फ़ाइल खोलें, तो इसे पूरी तरह से स्मृति में लोड किया जा रहा है।]

+0

एक एक्सेल फ़ाइल तब बनाई जाती है जब addAnswerRow() को एक बार बुलाया जाता है। यह मेरा झूठा है कि मैंने फ़ंक्शन को addAnswerRow() के रूप में नामित किया है। इसे createAnswerExcel() कहा जाना चाहिए। इसे बार-बार कहा जाता है। मैं आपके सुझाव का पालन करूंगा। :) – RedWolf

0

-verbose का उपयोग करें: जीसी जेवीएम विकल्प आसानी से यह जांचने के लिए कि क्या बीसीसी थ्रैशिंग के कारण मंदी हुई है।

0

ढेर आकार में वृद्धि से मदद मिल सकती है। आप -Xms और -Xmx तर्कों सहित न्यूनतम और अधिकतम ढेर आकार को सेट करने का प्रयास कर सकते हैं। निम्न आदेश न्यूनतम ढेर आकार 512 एमबी और अधिकतम ढेर 1024 एमबी के रूप में सेट करेगा।

जावा -Xms512m -Xmx1024m MyProgram

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