web-dev-qa-db-ja.com

POIのパフォーマンス

J2EEWebアプリケーションでPOIを使用してワークブックを生成しています。ただし、POIが25K行(それぞれ約15列)のワークブックを作成するのに約3分かかることがわかりました。これはPOIのパフォーマンスの問題ですか、それともそれだけの時間をかけることが正当化されますか?より良いパフォーマンスで知られている他のAPIはありますか?

19
The Machine

POIがそのようなファイルを生成するのにこれほど多くの時間がかかるのを見ると非常に驚きます。約18秒で30000行x10セルのシートを生成しました(公平を期すためにフォーマットなし)。原因は次のいずれかである可能性があります。

  • 説明されているように、POIロギングがオンになっている可能性があります ここ
  • スワップメモリ​​から実行しています
  • VM使用可能なヒープが非常に少ない可能性があります

標準のPOIAPIの代わりに「ストリーミング」POIAPIを使用すると、POIを使用して大きなファイルを書き込むパフォーマンスが大幅に低下する可能性があります。実際、デフォルトでは、POIは、最後に一度にすべてを書き込む前に、すべてのデータをメモリに保持します。これのメモリフットプリントは、大きなファイルの場合、途方もなく大きくなる可能性があります。代わりに、ストリーミングAPIを使用して、メモリの使用方法とデータのディスクへの書き込み方法を段階的に制御できます。

ストリーミングワークブックを作成するには、次のようなものを使用します。

  SXSSFWorkbook book = new SXSSFWorkbook(); 
  book.setCompressTempFiles(true);

  SXSSFSheet sheet = (SXSSFSheet) book.createSheet();
  sheet.setRandomAccessWindowSize(100);// keep 100 rows in memory, exceeding rows will be flushed to disk
  // ...
14
Eric Nicolas

他の答えがうまくいかない場合は、AndyKhanのJExcelが優れているかどうかを確認してください。 JavaでExcelを処理する点で、POIよりもはるかに優れていることがわかりました。

3
duffymo

また、WebアプリでPOIを使用しており、パフォーマンスの問題はありません。ただし、生成されたドキュメントはあなたのドキュメントよりはるかに小さいです。ここで、POIが本当の問題であるかどうかを最初に確認します。 J2EEオーバーヘッド(単体テスト)なしでこれらのドキュメントを生成し、パフォーマンスを測定してみてください。また、J2EEサーバーの負荷とメモリ使用量を監視して、問題が最適ではないシステム設定に起因するかどうかを確認することもできます。

1
pitpod

ApachePOIをJExcelライブラリと比較しました。 JExcelはApachePOIよりも最大で約4倍速いようですが、メモリ消費量はほぼ同じようです。

@Test
public void createJExcelWorkbook() throws Exception {
        WritableWorkbook workbook = Workbook.createWorkbook(new File("jexcel_workbook.xls"));
        WritableSheet sheet = workbook.createSheet("sheet", 0); 
        for ( int i=0; i < 65535; i++) {
            for ( int j=0; j < 10; j++) {
                Label label = new Label(j, i, "some text " + i + " " + j);
                sheet.addCell(label);
            }
        }
        workbook.write();
        workbook.close();
}

@Test
public void createPoiWorkbook() throws Exception {
    Workbook wb = new HSSFWorkbook();
    Sheet sheet = wb.createSheet("sheet");  
    for ( int i=0; i < 65535; i++) {
        Row row = sheet.createRow(i);
        for ( int j=0; j < 10; j++) {
            Cell cell = row.createCell(j);
             cell.setCellValue("some text " + i + " " + j);
        }
    }   
    FileOutputStream fileOut = new FileOutputStream("poi_workbook.xls");
    wb.write(fileOut);
    fileOut.close();
}

JExcelバージョン2.6.12とApachePOIバージョン3.7でテストしました。より正確な数値を取得するには、最新のライブラリバージョンを自分でダウンロードし、上記の簡単なテストを実行する必要があります。

<dependency org="org.Apache.poi" name="poi" rev="3.7"/>
<dependency org="net.sourceforge.jexcelapi" name="jxl" rev="2.6.12"/>

注: ApachePOIにはシートあたり65535行の制限があります。

1
andi