2010-03-23 9 views
17

J'utilise POI dans mon application Web J2EE pour générer un classeur. Cependant, je trouve que POI prend environ 3 minutes pour créer un classeur avec 25K lignes (avec environ 15 colonnes chacun). S'agit-il d'un problème de performance de POI ou est-il justifié de prendre autant de temps? Y a-t-il d'autres API connues pour de meilleures performances?POI performance

+0

@Gugusse, les réponses acceptées sont un indicateur pour ceux qui lisent la question ce que le _asker_ considéré comme la bonne réponse à sa/son problème réel. C'est un élément d'information très important. Cela dit, pour une raison quelconque, vous n'avez pas commenté le besoin pour le demandeur de fournir un extrait de code minimal montrant le comportement décrit? –

+0

@Gugussee, il ne fait que deviner. La raison réelle pourrait être n'importe quoi, que l'échantillon de code montrerait immédiatement. Serait-il raisonnable de vous suggérer d'améliorer votre méta-police? –

+0

@ Thorbjørn Ravn Andersen: Serait-il raisonnable de vous suggérer d'améliorer votre méta-méta-police? ;) – Gugussee

Répondre

12

Je serais très surpris de voir que POI met autant de temps à générer un tel fichier. Je viens de générer une feuille avec 30000 lignes x 10 cellules dans environ 18s (pas de mise en forme, pour être juste). La cause pourrait être l'un des éléments suivants:

  • enregistrement de POI peut être activée, comme décrit here
  • vous utilisez de la mémoire de swap
  • votre tas disponible VM peut être très faible
+0

Est-ce que les caractères internationaux rendront le traitement plus lent? Et une autre question, comment augmenter la mémoire VM améliorer les performances? –

+0

Je ne crois pas que les caractères internationaux rendraient ce type de traitement plus lent: il s'agit principalement de la quantité de données. En ce qui concerne le tas disponible VM, comme la quantité de mémoire requise se rapproche du tas disponible, le ramasse-miettes doit lancer plus souvent: dans les cas extrêmes, la plus grande partie du temps CPU est consacrée à la collecte des ordures. C'est une situation spécifique: il est peu probable que vous en soyez significativement affecté. –

+3

selon mon expérience POI est un peu lent et si POI a besoin d'une charge de mémoire *** ou doit être désactivé, alors c'est certainement un problème de POI. Nous générons des rapports à l'aide de POI et dès que nous générons plus de quelques feuilles de calcul, il devient très lent. En outre, 30000 lignes x 10 cellules est vraiment une infime quantité de données pour un processeur qui fait des milliards de cycles par seconde. Donc, oui, POI est une API assez lente. – Gugussee

1

Nous utilisons également les POI dans notre application web et nous n'avons aucun problème de performance avec elle - bien que nos documents générés soient beaucoup plus petits que les vôtres. Je voudrais d'abord vérifier si POI est le vrai problème ici. Essayez de générer ces documents sans le surdébit J2EE (Unit-Test) et mesurez les performances. Vous pouvez également surveiller l'utilisation de la charge et de la mémoire sur votre serveur J2EE pour voir si les problèmes proviennent de paramètres système sous-optimaux.

3

Si aucune des autres réponses ne fonctionne, voyez si le JExcel d'Andy Khan sera meilleur. Je l'ai trouvé pour être loin supérieur à POI pour traiter avec Excel en Java.

1

J'ai comparé le POI Apache avec la librairie JExcel. Il semble que JExcel est sur le point jusqu'à 4 fois plus rapide que Apache POI, mais la consommation de mémoire semble être plus ou moins le même:

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

Je l'ai testé avec la version JExcel 2.6.12 et la version Apache POI 3.7. Vous devez vous-même télécharger les dernières versions de la bibliothèque et exécuter les tests simples ci-dessus pour obtenir des chiffres plus précis.

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

Note: il y a une limite dans Apache POI de 65535 lignes par feuille.

+4

La limite de ligne est une limitation de format de fichier Excel .xls, pas un POI. Si vous utilisez le format de fichier .xlsx (en utilisant XSSF d'Apache POI), vous pouvez créer plus de lignes – Gagravarr

9

Les performances de l'écriture de fichiers volumineux avec POI peuvent être fortement réduites si vous utilisez l'API POI 'streaming' au lieu de l'API standard. En effet, par défaut, POI gardera toutes vos données en mémoire avant d'écrire tout d'un coup à la fin. L'empreinte mémoire de ceci peut être ridiculement grande pour les gros fichiers. Au lieu d'utiliser l'API de diffusion en continu, vous pouvez contrôler l'utilisation de la mémoire et l'écriture progressive des données sur le disque.

Afin de créer un classeur de diffusion en continu, utilisez quelque chose comme:

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