2010-02-26 4 views
5

Tôi đang sử dụng chương trình để gửi dữ liệu từ cơ sở dữ liệu sang tệp Excel. Nó hoạt động tốt ở đầu và sau đó trở nên ngày càng chậm, cuối cùng nó chạy ra khỏi bộ nhớ và các lỗi sau đây ocurrs: "java.lang.OutOfMemoryError: Java heap space ...".Tại sao chương trình của tôi nhận được chậm hơn và chậm hơn?

Sự cố có thể được giải quyết bằng cách thêm jvm heap sapce.But câu hỏi là nó dành quá nhiều thời gian để chạy chương trình.

Sau vài phút, nó hoàn thành một vòng lặp với 4 giây có thể hoàn thành với 0,5 giây ngay từ đầu. Tôi không thể tìm thấy một giải pháp để làm cho nó luôn luôn chạy ở một tốc độ nhất định.

Có phải vấn đề về mã của tôi không?

Bất kỳ manh mối nào về điều này?

Đây là mã:

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

(Tiếp theo những nhận xét dưới đây) Bạn không cần phải giải thích nó một cách chi tiết .. Ví dụ, "Tôi lấy hai tờ mà cả hai đều có một chìa khóa thông thường (StudentID hoặc một cái gì đó ??) và tham gia cùng họ "hoặc một cái gì đó. Sau đó, chúng tôi có thể khuyên bạn sử dụng sắp xếp hợp nhất để sắp xếp các trang tính này trước tiên, bằng không gian đĩa và sau đó bạn có thể lặp qua cả hai trang tính mà không cần sử dụng bộ nhớ ... –

Trả lời

9

Một nơi nào đó bạn đang tạo các đối tượng và giữ lại tài liệu tham khảo có thể truy cập đối với họ.

Có thể bạn đang thêm đối tượng vào bộ sưu tập và không bao giờ xóa chúng ... do đó bộ sưu tập chỉ phát triển cho đến khi bạn hết bộ nhớ. Khi bạn nhận được gần với kích thước heap tối đa các bộ thu rác là quá thuế để tìm bộ nhớ miễn phí để tổ chức lại mọi thứ và chương trình nhận được theo cấp số nhân chậm hơn gần bạn nhận được đến giới hạn.

Ngoài ra, bạn có thể quên đóng một số đối tượng mỗi lần, chẳng hạn như sổ làm việc của bạn.

+0

Nghe có vẻ không thể tránh. tạo các đối tượng để giữ dữ liệu từ cơ sở dữ liệu và thời gian khi công việc GC không được giải quyết. Ngoài ra Sổ làm việc được đóng vào cuối: book.close() – RedWolf

+0

Mã khó theo dõi ... bạn có thể giải thích ngắn gọn những gì bạn đang cố gắng đạt được không? Sau đó, chúng tôi có thể xem liệu nó (có một bộ sưu tập lớn) thực sự không thể tránh được (Nếu nó thực sự không thể tránh được, bạn vẫn có thể sử dụng đĩa vì vậy đừng lo lắng ..) –

+0

@Zwei: Bạn có thể muốn chuyển nhận xét của bạn cho câu hỏi ... Tôi không nghĩ rằng RedWolf sẽ được thông báo nếu nó nằm trong câu trả lời của tôi. –

1

Khi ứng dụng của bạn đang chạy ra khỏi không gian heap, nó sẽ mất nhiều thời gian hơn trong GC cố gắng để lấy lại không gian trước khi cuối cùng từ bỏ và ném một OutOfMemoryError. Tôi khuyên bạn nên làm như sau:

  • thêm -XX:+UseGCOverheadLimit tùy chọn JVM làm cho JVM thất bại trước đó khi hết bộ nhớ.

  • sử dụng một hồ sơ bộ nhớ để tìm kiếm bộ nhớ có thể bị rò rỉ

  • nếu bạn không thể tìm thấy bất kỳ rò rỉ, chỉ tăng kích thước heap.

Nếu bạn vẫn nhận được hiệu ứng chậm với một đống lớn hơn, vấn đề có thể liên quan đến thuật toán đang được sử dụng. Trong trường hợp đó, bạn cần sử dụng một trình lược tả thực thi để tìm ra nơi ứng dụng của bạn dành phần lớn thời gian của nó.

[Lý thuyết: Nếu số addAnswerRow của bạn được gọi liên tục, sự cố có thể liên quan đến việc mở tệp bảng tính Xcel liên tục trở nên lớn hơn với mỗi cuộc gọi addAnswerRow. Có thể mỗi khi bạn mở tệp, tệp đó sẽ được tải toàn bộ vào bộ nhớ.]

+0

Một tệp excel được tạo khi addAnswerRow() được gọi là once.It là false của tôi mà tôi đã đặt tên hàm là addAnswerRow(). Nó sẽ được gọi là createAnswerExcel(). Nó được gọi là thực sự nhiều lần. Tôi sẽ làm theo đề xuất của bạn. :) – RedWolf

0

Sử dụng tùy chọn JVM -verbose: gc JVM để dễ dàng kiểm tra xem sự chậm lại có phải do GC đập hay không.

0

Tăng kích thước heap có thể hữu ích. Bạn có thể thử đặt kích thước heap tối thiểu và tối đa bằng cách bao gồm các đối số -Xms và -Xmx. Lệnh sau sẽ đặt kích thước heap tối thiểu là 512 MB và tối đa heap là 1024 MB.

java -Xms512m -Xmx1024m MyProgram