2010-03-23 5 views
17

Sto utilizzando POI nella mia applicazione web J2EE per generare una cartella di lavoro. Tuttavia, trovo che il POI impiega circa 3 minuti per creare una cartella di lavoro con 25K righe (con circa 15 colonne ciascuna). Si tratta di un problema di prestazioni POI o è giustificato impiegare così tanto tempo? Esistono altre API note per prestazioni migliori?Prestazioni POI

+0

@Gugusse, Si accettano le risposte sono un indicatore a quelle leggere alla domanda che cosa la _asker_ considerato la risposta giusta alla sua/il suo problema reale. Questa è un'informazione molto importante. Detto questo, qualsiasi motivo per cui non hai commentato la necessità per il richiedente di fornire uno snippet di codice minimo che mostri il comportamento descritto? –

+0

@ Gugussee, sta solo supponendo. Il vero motivo potrebbe essere qualsiasi cosa, che l'esempio di codice mostrerebbe immediatamente. Sarebbe ragionevole suggerire di migliorare la tua meta-polizia? –

+0

@ Thorbjørn Ravn Andersen: sarebbe ragionevole suggerire di migliorare la meta-meta-polizia? ;) – Gugussee

risposta

12

Sarei molto sorpreso di vedere POI prendere così tanto tempo per generare un tale file. Ho appena generato un foglio con 30000 righe x 10 celle in circa 18 secondi (nessuna formattazione, per essere onesti). La causa potrebbe essere una delle seguenti:

  • registrazione POI sia acceso, come descritto here
  • si esegue a memoria di swap
  • vostro VM disponibili mucchio potrebbe essere molto bassa
+0

La presenza di caratteri internazionali renderà l'elaborazione più lenta? E un'altra domanda: in che modo l'aumento della memoria VM può migliorare le prestazioni? –

+0

Non credo che i personaggi internazionali renderebbero questo tipo di elaborazione più lento: si tratta principalmente della quantità di dati. Per quanto riguarda l'heap disponibile della VM, poiché la quantità di memoria richiesta si avvicina all'heap disponibile, il garbage collector deve eseguire il kick-in più spesso: in casi estremi, la maggior parte del tempo della CPU viene utilizzato per la raccolta dei dati inutili. Questa è una situazione specifica: non è probabile che tu ne sia significativamente influenzata. –

+3

nella mia esperienza POI è un po 'lento e se il POI ha bisogno di un carico di memoria o necessita di registrazione per essere spento, allora sicuramente ** è ** un problema di POI. Generiamo report usando POI e non appena generiamo più di un foglio di calcolo diventa molto lento. Inoltre, 30000 righe x 10 celle sono in realtà una piccola quantità di dati per una CPU che genera miliardi di cicli al secondo. Quindi, sì, POI è un'API piuttosto lento. – Gugussee

1

Usiamo anche POI nella nostra app Web e non abbiamo alcun problema di prestazioni con esso - anche se i nostri documenti generati sono molto più piccoli dei tuoi. Vorrei innanzitutto verificare se il POI è il vero problema qui. Prova a generare quei documenti senza l'overhead J2EE (Unit-Test) e misurare le prestazioni. È anche possibile monitorare il carico e l'utilizzo della memoria sul server J2EE per verificare se i problemi derivano da alcune impostazioni di sistema non ottimali.

3

Se nessuna delle altre risposte funziona, verifica se JExcel di Andy Khan sarà migliore. Ho trovato che è di gran lunga superiore a POI per trattare con Excel in Java.

1

Ho confrontato Apache POI con la libreria JExcel. Sembra che JExcel sta fino a 4 volte più veloce di Apache POI, ma il consumo di memoria sembra essere più o meno lo stesso:

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

ho provato con JExcel versione 2.6.12 e Apache POI versione 3.7. È necessario scaricare da solo le ultime versioni della libreria ed eseguire i test semplici sopra per ottenere numeri più precisi.

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

Nota: c'è un limite in Apache POI di 65535 righe per foglio.

+4

Il limite di riga è un limite di formato file .xls di Excel, non uno di tipo PDI. Se si utilizza il formato file .xlsx (utilizzando XSSF da POI Apache), è possibile creare più righe – Gagravarr

9

Le prestazioni di scrittura di file di grandi dimensioni con POI possono essere fortemente ridotte se si utilizza l'API di POI "streaming" anziché quella standard. Infatti, di default POI manterrà tutti i tuoi dati in memoria prima di scrivere tutto in un colpo solo alla fine. L'impronta di memoria di questo può essere ridicolmente grande per i file di grandi dimensioni. Invece utilizzando l'API di streaming è possibile controllare come viene utilizzata la memoria e i dati vengono scritti su disco progressivamente.

Al fine di creare una cartella di lavoro in streaming, usare qualcosa come:

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 
    // ...