ShortShip

13 December 2008

JExcelAPI and Garbage Collection

One of the Java based reporting applications I currently work on has an Excel export feature. For this application I chose the JExcelApi library because I had read that it performs slightly better than the other open source alternatives and that its API was less verbose and generally easier to use. In my dev environment I had no issues with performance but in the staging and production environments, the Excel export was painfully slow. It would sometimes take up to 30 seconds to generate a single page Excel report. After running the code through a profiler I determined there were no bottlenecks in the code nor in the JExcelAPI library itself. The only significant difference between my dev environment and the staging and production environments was that the application in the later two environments would load the full dataset whereas my dev environment loaded a significantly smaller dataset. This meant a difference in heap sizes of 100 MB in dev vs ~12GB in staging/production (don’t ask). 

I theorized that garbage collection was the culprit here. However, I was reluctant to believe this since the Excel reports being generated were fairly small and it didn’t seem to me that a single request would be enough to trigger a full garbage collection given the maximum amount of memory the application was allowed to use (16 GB).  

Using VisualVM I monitored my local dev tomcat instance in attempt to prove my theory.

As you can see above, the two green arrows show two peaks in CPU utilization and Garbage Collection Activity. These two peaks appeared when I used the Excel export option in the application. At this point it seemed my theory was correct but to be sure I used the JVM option “-verbose:gc” to log GC activity in the staging environment. Sure enough, each time I used Excel export, the JVM would perform a full garbage collection. 

After much research I finally discovered what was going on. According to the JavaDoc for the WorkbookSettings class:

/**

  * Flag to indicate whether the system hint garbage collection

  * is enabled or not.

  * As a rule of thumb, it is desirable to enable garbage collection

  * when reading large spreadsheets from a batch process or from the

  * command line, but better to deactivate the feature when reading

  * large spreadsheets within a WAS, as the calls to System.gc() not

  * only garbage collect the junk in JExcelApi, but also in the

  * webservers JVM and can cause significant slowdown

  * GC deactivated using -Djxl.nogc=true on the JVM command line

  * Activated by default or by using -Djxl.nogc=false on the JVM command line

  */

private boolean gcDisabled;”

So, JExcelApi by default will ask the JVM to perform a full garbage collection after certain operations. As the JavaDoc recommends, I added “-Djxl.nogc=true” to my JVM options and the delays went away. I have not seen this mentioned anywhere on JExcelApi’s website so If you face a similar problem with performance, try enabling this flag.

No related posts.

4 Comments currently posted.

Radhika Ganesan says:

Thank you, it a nice explanation for a rookie like me ! Though did not understand the JVM setting related part since i haven’t worked on it , but still the basic idea is clear. I have to give presentation about JMesa (a new data grid tech.) and it has options for EXCEL and JEXCEL , i was wondering why these options are there ? Now i have a basic idea of the same !!

pedro says:

Thanks a lot for this…. spent the hole day chasing this issue…. same thing exactly. No problem on the development stations but when it goes to acceptance… massive slow down”

Saw the stacktrace showing a call to System.gc(); from jxl.SheetImpl

NOW I see your blog…. :)

Fixing jExcel’s performance issue while running in a web application « LaneHolloway.com says:

[...] information by one of my coworkers who was looking at the high level and stumbled upon it through this website (I would have eventually found this bit comment, but I’m glad he did since it saved me a lot [...]

Edi says:

Thanks for the post. Massive difference in performance :D

Post a comment on this entry: