Jump to content

Poor JR Performance and Text Measuring


henstockjohn

Recommended Posts

We are looking to deliver reports which have very high performance targets (two different datasources 500k/50k rows with two subreports). A report break is on an Account code where there are 900 accounts so I believe this would account for 1800 subreports. We are utilizing the Custom DS to stream data.

 We are using a dev box with Cent OS linux and 4 GB RAM (of 64 GB RAM  with 8 CPUs) allocated to a report generator application. In a crude comparison we have found that JR takes 5 times as long as querying the same data and writing to disk.

We have spent several weeks investigating performance and basically have found what others have found in terms of the text measuring implementation, where:

"...The problem is caused because of the way Jasper uses TextMeasurer - AWT print implementation. It uses the AttributedString, TextLayout and LineBreakMeasurer classes which are AWT Graphics 2D classes thereby affecting the performance while filling the reports. It renders string text by using antiAliasing properties and uses fractionalMetrics - decimal precision for filling texts.."

At this point we are looking at writing our own implementation of "net.sf.jasperreports.engine.fill.JRTextMeasurerFactory" to attempt to bypass the AWT classes. The alternative is to abandon usage of JR.

I have to assume that because there are no examples of an implementation on this site or on the web that this is no easy task. This is compounded by the fact that there is no JR switch available.

I would really appreciate feedback from the project team in terms of their approx development effort estimates of writing such an implementation. Of course we would be willing to share our findings with the project community.

Regards,
John

Link to comment
Share on other sites

  • Replies 11
  • Created
  • Last Reply

Top Posters In This Topic

Some micro-optimizations on TextMeasurer.java:

  • By default, StringBuffer uses a 16 byte internal array. Appending beyond that length uses an array copy. Change line 499 to:
    • StringBuffer lineText = new StringBuffer( 2048 );
  • Swap a StringBuilder for a StringBuffer, if you need not worry about multithreading.
  • Assignment of instance variables to 0, null, or false is redundant (you can safely remove "= 0" from instance variable declarations). This should be done throughout the code base as the compiler will not do this automatically.
  • Lines 515 and 566 use string concatenation; eliminate it in favour of a StringBuilder (or StringBuffer).
  • The truncateSuffx.length() is probably going to be optimized by a JIT, but I would assign it to a variable anyway and reuse that variable.
  • Try moving variables like linePosition and lineStart to the top of the method (variables declared first use shorter bytecodes).

Other things to try:

  • Check the performance against other JVMs, such as:
    • JDK 1.7
    • Oracle's JRockit
  • Make sure you are using JR 3.7.3

I would be interested in any performance improvements you make. I'm also interested in seeing the lines that are the performance bottleneck.

I would also look at hardware, if possible. Some RAM that is rated for 1600MHz will only perform at 1600MHz with a specific processor, using specific settings (that can depend on the RAM's voltage). Make sure that the BIOS has optimized the hardware.

What's the size of the buffer for the custom data source stream?



Post Edited by thangalin at 06/27/2010 08:42
Link to comment
Share on other sites

henstockjohn
Wrote:

At this point we are looking at writing our own implementation of "net.sf.jasperreports.engine.fill.JRTextMeasurerFactory" to attempt to bypass the AWT classes. The alternative is to abandon usage of JR.

I have to assume that because there are no examples of an implementation on this site or on the web that this is no easy task. This is compounded by the fact that there is no JR switch available.

The JasperServer codebase contains a faster text measurer implementation that can be used for non-stretching text elements.  See at http://jasperforge.org/scm/viewvc.php/trunk/jasperserver-api-impl/engine/src/main/java/com/jaspersoft/jasperserver/api/engine/jasperreports/util/SingleLineTextMeasurer.java?root=jasperserver&view=log

Before advancing any estimate on writing a new implementation, one would need to decide how that would work.  How exactly do you plan to measure texts?

Regards,

Lucian

Link to comment
Share on other sites

We have implemented our own Text Measurer, the assumptions made in the Text Measurer are :-

1) Text will always be displayed in a single row. If text exceeds the size of the Text box, the remaining text will be truncated. Text cannot be displayed in columnar format or in paragraph.

2) Static Texts must be wrapped in the text box with as less space possible, both vertical and horizontal ways.

3) Ht of the text box places significant role in measuring pixels for the text. So for dynamic text, the height of the text box must be kept just sufficient to wrap the text.

4) Empirical factors are used in calculating the leading offset, height, no of characters, spacing factor. The empirical factors works fine for SansSerif font - in the range of font size 10-14. For fonts of different family and sizes, these factors will change. Further testing is required for other fonts.


Initial tests show minute pixel mis-alignment but it's 3 times faster.

 

Lucian - the classes for StyleInfo and StyleInfoPool seem to be unavailable.


Thanks

 

Link to comment
Share on other sites

StyleInfo and StyleInfoPool are located in the same package as the SingleLineTextMeasurer class.

You can upload your text measurer implementation as a patch via the project trackers if you'd like it to be taken into consideration for inclusion in JR.

Thank you,

Lucian

Link to comment
Share on other sites

lucianc
Wrote:

 

The text measurer has been written by someone working on JasperServer.  We've been considering moving it into JR.

 

Adding it to JR has our vote.  We had a Jasper consultant come in and tell us about it. So, we use it on some reports that are located on JasperServer.  The pain is when we need to change these reports. They don't work when ran from iReport because the class is not found.

We also run reports on a IBM i5 using JasperReports, so it would be nice to have this performance tweak available for those reports too.

Thanks,  Scott

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...