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
risposta
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
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? –
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. –
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
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.
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.
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.
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
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
// ...
@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? –
@ 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? –
@ Thorbjørn Ravn Andersen: sarebbe ragionevole suggerire di migliorare la meta-meta-polizia? ;) – Gugussee