简体   繁体   English

为什么我的程序越来越慢?

[英]Why is my program getting slower and slower?

I'm using the program to send data from database to the Excel file . 我正在使用该程序将数据从数据库发送到Excel文件。 It works fine at the beginning and then becomes more and more slowly,finally it run out of the memory and the following error ocurrs: "java.lang.OutOfMemoryError: Java heap space...". 它在开始时工作正常然后变得越来越慢,最后它耗尽了内存并出现以下错误:“java.lang.OutOfMemoryError:Java堆空间......”。

The problem can be resolved by adding the jvm heap sapce.But the question is that it spends too much time to run out the program. 可以通过添加jvm堆sapce来解决这个问题。但问题是它花了太多时间来运行程序。

After several minutes,it finished a loop with 4 seconds which can be finished with 0.5 seconds at the beginning . 几分钟后,它完成一个4秒的循环,可以在开始时0.5秒完成。 I can't found a solution to make it always run in a certain speed. 我无法找到一个解决方案,使它始终以一定的速度运行。

Is it my code problem? 这是我的代码问题吗?

Any clues on this? 这有什么线索吗?

Here is the code: 这是代码:

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();
   }

} } }}

Somewhere you are creating objects and retaining reachable references to them. 在某处您正在创建对象并保留对它们的可访问引用。

You are probably adding objects to a collection and never removing them... so the collection just grows until you run out of memory. 您可能正在将对象添加到集合中,并且永远不会删除它们...因此集合只会增长,直到内存不足为止。 As you get close to the maximum heap size the garbage collector is over-taxed to find free memory to reorganize things and the program get exponentially slower the closer you get to the limit. 当你接近最大堆大小时,垃圾收集器被过度征税以找到可用内存来重新组织事物,程序越接近限制就会以指数方式变慢。

Also, it's possible you are forgetting to close some object(s) each time through, such as your workbook. 此外,您可能忘记每次关闭某些对象,例如您的工作簿。

I highly suspect that there is a memory leak on your program. 我非常怀疑您的程序存在内存泄漏。 Use profiler like JProfiler or YourKit to detect memory leak. 使用JProfiler或YourKit等探测器来检测内存泄漏。 Maybe you forgot to close the WritableWorkbook? 也许你忘了关闭WritableWorkbook?

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

When your application is running out of heap space, it will take more and more time in the GC trying to reclaim space before eventually giving up and throwing an OutOfMemoryError. 当您的应用程序用尽堆空间时,GC会花费越来越多的时间尝试回收空间,最终放弃并抛出OutOfMemoryError。 I recommend doing the following: 我建议做以下事情:

  • add the -XX:+UseGCOverheadLimit JVM option to cause the JVM to fail earlier when it is running out of memory. 添加-XX:+UseGCOverheadLimit JVM选项可使JVM在内存不足时更早失败。

  • use a memory profiler to look for possible memory leaks 使用内存分析器查找可能的内存泄漏

  • if you cannot find any leaks, just increase the heap size. 如果找不到任何泄漏,只需增加堆大小即可。

If you still get slowdown effects with a bigger heap, the problem may be something to do with the algorithms being used. 如果您仍然使用更大的堆获得减速效果,则问题可能与所使用的算法有关。 In that case, you need to use an execution profiler to figure out where your application is spending most of its time. 在这种情况下,您需要使用执行分析器来确定应用程序在大部分时间内花费的时间。

[Theory: If your addAnswerRow is being called repeatedly, the problem could be related to repeatedly opening an Xcel spreadsheet file that is getting larger each with each addAnswerRow call. [理论:如果重复调用addAnswerRow ,问题可能与重复打开每个addAnswerRow调用越来越大的Xcel电子表格文件有关。 It is possible that each time you open the file, it is being loaded into memory in its entirety.] 每次打开文件时,它都可能被整个加载到内存中。

使用-verbose:gc JVM选项可以轻松检查减速是否由GC抖动引起。

Increasing the heap size might help. 增加堆大小可能会有所帮助。 You can try setting the min and max heap size by including -Xms and -Xmx arguments. 您可以尝试通过包含-Xms和-Xmx参数来设置最小和最大堆大小。 The following command will set min heap size as 512 MB and max heap as 1024 MB. 以下命令将最小堆大小设置为512 MB,最大堆设置为1024 MB。

java -Xms512m -Xmx1024m MyProgram java -Xms512m -Xmx1024m MyProgram

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM