On Feb 15, 2008, at 20:37, Puppala, Kumar (LNG-CON) wrote:

Hi Kumar

<snip />
Well, it's not so much the number of objects I'm thinking of, but
rather, how much time is spent executing specific methods and which
ones take longer in later iterations. The actual cause of the
slowdown may precisely be located in a class of which there are
relatively few instances alive, if I judge correctly. Or did you
already check whether the bulk of the increase in processing-time is
really only spent on garbage-collection?

--> I did verify that garbage collection is playing a very significant role in these increased timings. I am currently using the Java Profiling tool to identify the methods where we have the maximum execution time. I ran the basic simple.fo file provided in the examples directory and below is the screen shot from the profiling tool:

<image001.jpg>

I need to do further analysis on this but comparing this output to the one generated by running the same fo file against fop 0.20.5 codebase, I do see two significant areas (lineBreak and layoutMgr) that are taking time. The profiling output for the same test on fop 0.20.5 codebase is as shown below:


Unfortunately, a single run is far from representative, especially when compared to the set of tests you ran earlier.

What one could say, based on the screenshot, is that most of the time is spent on parsing the FO and on creating loggers, but then we would be conveniently ignoring the simple facts that: * all loggers are static, so the cost of creating them is overly represented if you measure only a single run (hence why LogFactory is at the top of the list here) * the org.apache.fop.fo package contains a lot of static initialization as well, so ... (unfortunately, no details shown in the screenshot to confirm)

In the meantime, I have run some local tests using the files you published. Thanks for those! The tests were run as an iteration of the most basic example ExampleFO2PDF.java, slightly modified to process the whole set of files you provided one-by-one, using a specified maximum number of concurrently running threads.

So far, I have run:
1 batch of 1500 runs, single-threaded
1 batch of 1500 runs, in two threads
1 batch of 1500 runs, in three threads
1 batch of 3000 runs, in 10 threads.

I did not immediately see any indication of individual tests consistently taking longer in later iterations. Each of the 117 files was processed about 13 times in the course of one batch of 1500, 26 times for the batch of 3000. Some run a tiny bit slower, but IMO not enough to count as actually 'slower'. Some tests are even faster the 13th time around than the first time.

I do see some runs taking significantly longer, most likely due to garbage-collection. This effect can already be observed when running in a single thread.

As potential improvements:
There are some tests that generate a significant amount of log- messages (mostly warnings). AFAICT, if you can make your generated FO such that it produces less of these warnings, there could already be a noticeable speed-benefit. The processing times in my tests were always a lot higher for those tests that generated a lot of warnings.

To reduce the strain on the garbage-collector, you could also consider generating 'better' FO.

Of course, this is a matter of opinion, but one striking example I encountered is the pattern:

<fo:block space-after="1em"/>
<fo:block text-indent="0.250000in">
  <fo:inline ...font-properties....>#PCDATA</fo:inline>
</fo:block>
<fo:block space-after="1em"/>

The above construct is (in most situations) equivalent to:

<fo:block space-before="1em" space-after="1em"
          text-indent="0.250000in"
          ...font-properties...>#PCDATA</fo:block>

IOW, by inserting empty fo:blocks and extra fo:inlines, the first pattern, which is extensively used in the test-FOs, generates a lot of Java objects which are, strictly speaking, completely unnecessary.
If you could iron that out, you're also bound to see an improvement.
As rules of thumb:
- empty fo:blocks should be avoided at any cost; sometimes, preserved linefeeds generate the same effect with much less overhead - fo:inlines should only be used when absolutely necessary (to change certain properties inline); in the above example, it serves no particular purpose apart from carrying the font-related properties, while those could just as well be specified on the surrounding fo:block.


I'll keep running some more tests and will report back if I have any news.


Cheers

Andreas

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to