【问题标题】:Why is my program getting slower and slower?为什么我的程序越来越慢?
【发布时间】:2010-02-26 06:32:38
【问题描述】:

我正在使用该程序将数据从数据库发送到 Excel 文件。 刚开始运行正常,然后越来越慢,最后内存耗尽,出现以下错误:“java.lang.OutOfMemoryError: Java heap space...”。

这个问题可以通过添加jvm heap 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();
   }

} }

【问题讨论】:

  • (接下面的评论)你不需要详细解释。例如,“我正在拿两张都有共同键(studentId什么的??)和加入他们”之类的。然后我们可以建议您首先使用合并排序对这些工作表进行排序,使用磁盘空间,然后您可以在不使用大量内存的情况下遍历这两个工作表...

标签: java memory memory-management jvm


【解决方案1】:

您在某个地方创建对象并保留对它们的可访问引用。

您可能正在将对象添加到集合中并且永远不会删除它们......所以集合只会增长直到您耗尽内存。当您接近最大堆大小时,垃圾收集器会负担过重以寻找空闲内存来重组事物,并且程序会随着您接近限制而呈指数级变慢。

此外,您可能每次都忘记关闭某些对象,例如您的工作簿。

【讨论】:

  • 听起来是无法避免的。因为它必须创建对象来保存数据库中的数据,并且GC工作的时间是未知的。工作簿也在最后关闭:book.close()
  • 代码很难理解......你能简要解释一下你想要实现的目标吗?那我们也许可以看看它(有一个巨大的集合)是否真的无法避免(如果它真的无法避免,你仍然可以使用磁盘所以不用担心..)
  • @Zwei:你可能想把你的评论移到这个问题上……我认为如果它在我的回答之下,RedWolf 不会收到通知。
  • @SoftwareMonkey 如果@Zwei 使用过@RedWolf,OP 会收到通知 :)
  • @Zwei:代码可读性差,因为我发现很难简单解释,我会在内存分析后检查代码。刚才我只编辑代码使其整洁。谢谢。
【解决方案2】:

我高度怀疑您的程序存在内存泄漏。使用 JProfiler 或 YourKit 之类的分析器来检测内存泄漏。也许您忘记关闭 WritableWorkbook?

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

【讨论】:

  • 工作簿最后关闭。我要标记一个内存测试。 :)
【解决方案3】:

当您的应用程序用尽堆空间时,GC 将花费越来越多的时间尝试回收空间,然后最终放弃并抛出 OutOfMemoryError。我建议执行以下操作:

  • 添加-XX:+UseGCOverheadLimit JVM 选项以使JVM 在内存不足时提前失败。

  • 使用内存分析器查找可能的内存泄漏

  • 如果找不到任何泄漏,只需增加堆大小即可。

如果堆更大时仍会出现减速效果,则问题可能与所使用的算法有关。在这种情况下,您需要使用执行分析器来确定您的应用程序在哪里花费了大部分时间。

[理论:如果您的addAnswerRow 被重复调用,则问题可能与重复打开一个 Xcel 电子表格文件有关,该文件随着每次addAnswerRow 调用而变得越来越大。有可能每次打开文件时,它都会被全部加载到内存中。]

【讨论】:

  • 调用 addAnswerRow() 时会创建一个 excel 文件。我将函数命名为 addAnswerRow() 是我的错误。它应该被称为 createAnswerExcel()。它确实被反复调用。我会听从你的建议。 :)
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    增加堆大小可能会有所帮助。您可以尝试通过包含 -Xms 和 -Xmx 参数来设置最小和最大堆大小。以下命令会将最小堆大小设置为 512 MB,将最大堆设置为 1024 MB。

    java -Xms512m -Xmx1024m 我的程序

    【讨论】:

      猜你喜欢
      • 2018-04-21
      • 1970-01-01
      • 2015-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多