J2DBench does not have a regression test mode unfortunately.

Clipping in the stroker and dasher is doable, but it is complicated by the fact that stroking adds 
decorations that are not always easy to account for.  Round joins and end caps are easy - they 
"grow" the path by exactly half the line width.  Square and Butt caps and Bevel joins are equally 
predictable, you can do some trig or come up with an upper bound on how much they may "grow" the 
path in any given direction.  Miter joins are the hardest as it depends on the miter limit and the angle 
between the line segments.  Also, curves could be rejected based on conservative trivial estimates of the 
worst case of the path and the worst case of the stroke "grow" factor by using their 4 control 
points, but if you want something more exact then you have to subdivide them anyway.

And when you cull, you have to remember to update all of the state so that you know the 
"previous slope and join info" so that the next segment, which might not be 
culled, can interpolate the correct joins.

As with any culling, you have to measure the likelihood of success against the 
cost of the computations.  As such, it is probably best to perform the most 
conservative estimates before culling the paths so that you don't slow down 
some common cases of the path being fully visible.

I forget how the Renderer piece is written, but hopefully it culls segments 
that are outside the clip so that while we may waste time generating the dashes 
and widened paths for parts that are outside the clip, at least we don't spend 
time rasterizing them?

                        ...jim

On 3/28/2013 8:40 AM, Laurent Bourgès wrote:
Dear java2d members,

FYI: I now have a working patched java2d pisces that performs better: no memory 
waste (99%) and performance increased on complex operations (dashed ...); patch 
/ benchmark in progress ...

Does J2DBench have a regression test mode ?
i.e. capture screenshots (with few shapes) to compare them between different 
runs (image comparison pixel by pixel)

Besides, I found an important bug in pisces Stroker / Dasher: it does not use 
the clip region given to PiscesRenderingEngine.getAATileGenerator(clip).

In Aspro2, I can zoom on jFreeChart plots a lot and it draws shapes (rectangle 
or lines with dashed lines) then the dasher emits segments out of the visible 
area (millions in case of a important zoom) and the application hangs a for 
while (5s to minutes).

I would like to determine the shape part (line or any complex shape) that is 
inside the clip and avoid useless segments (Stroker / Dasher).

Does somebody have any idea ?
or know java2d.pisces code enough to help me ?

Laurent


2013/3/26 Laurent Bourgès <bourges.laur...@gmail.com 
<mailto:bourges.laur...@gmail.com>>

    Dear all,

    First I joined recently the openJDK contributors, and I plan to fix java2D 
pisces code in my spare time.

    I have a full time job on Aspro2: http://www.jmmc.fr/aspro; it is an 
application to prepare astronomical observations at VLTI / CHARA and is very 
used in our community (200 users): it provides scientific computations 
(observability, model images using complex numbers ...) and zoomable plots 
thanks to jFreeChart.

    Aspro2 is known to be very efficient (computation parallelization) and I am 
often doing profiling using netbeans profiler or visualVM.

    To fix huge memory usages by java2d.pisces, I started implementing an 
efficient ArrayCache (int[] and float[]) (in thread local to concurrency 
problems):
    - arrays in sizes between 10 and 10000 (more small arrays used than big 
ones)
    - resizing support (Arrays.copyOf) without wasting arrays
    - reentrance i.e. many arrays are used at the same time (java2D Pisces 
stroke / dash creates many segments to render)
    - GC / Heap friendly ie support cache eviction and avoid consuming too much 
memory

    I know object pooling is known to be not efficient with recent VM (GC is 
better) but I think it is counter productive to create so many int[] arrays in 
java2d.pisces and let the GC remove such wasted memory.

    Does someone have implemented such (open source) array cache (core-libs) ?
    Opinions are welcome (but avoid "trolls").

    Moreover, sun.java2d.pisces.Helpers.widenArray() performs a lot of array 
resizing / copy (Arrays.copyOf) that I want to avoid mostly:
         // These use a hardcoded factor of 2 for increasing sizes. Perhaps this
         // should be provided as an argument.
         static float[] widenArray(float[] in, final int cursize, final int 
numToAdd) {
             if (in.length >= cursize + numToAdd) {
                 return in;
             }
             return Arrays.copyOf(in, 2 * (cursize + numToAdd));
         }

         static int[] widenArray(int[] in, final int cursize, final int 
numToAdd) {
             if (in.length >= cursize + numToAdd) {
                 return in;
             }
             return Arrays.copyOf(in, 2 * (cursize + numToAdd));
         }

    Thanks to Peter Levart, I use its microbench tool 
(https://github.com/plevart/micro-bench/tree/v2) to benchmark ArrayCache 
operations... and J2DBench to test java2d performances

...


    PS: java.awt.geom.Path2D has also memory allocation issues:
             void needRoom(boolean needMove, int newCoords) {
                 if (needMove && numTypes == 0) {
                     throw new IllegalPathStateException("missing initial moveto 
"+
                                                         "in path definition");
                 }
                 int size = pointTypes.length;
                 if (numTypes >= size) {
                     int grow = size;
                     if (grow > EXPAND_MAX) {
                         grow = EXPAND_MAX;
                     }
                     pointTypes = Arrays.copyOf(pointTypes, size+grow);
                 }
                 size = floatCoords.length;
                 if (numCoords + newCoords > size) {
                     int grow = size;
                     if (grow > EXPAND_MAX * 2) {
                         grow = EXPAND_MAX * 2;
                     }
                     if (grow < newCoords) {
                         grow = newCoords;
                     }
                     floatCoords = Arrays.copyOf(floatCoords, size+grow);
                 }
             }

    Best regards,
    Laurent


Reply via email to