Jim,<br><br>There are finally only few growable arrays (edges, curves, rowAARLE) and now I have a working Pisces code (J2DBench pass OK) that performs better than current (2x - 3x faster on dasher or big shapes) using only few megabytes (Xmx32m) ...<br>
<br>Moreover, these arrays could be created once per thread (thread local) to avoid GC (low footprint) and enhance performance (no GC / array resizing or coyping) with an initial size of 4K or 16K representing only 16 x 4 = 65Kb !<br>
<br>The only array that causes troubles is the growable PiscesCache.rowAARLE[Y][tuples] which Y size depends on the shape / clip bounds and tuples depend on the crossing numbers at the current row Y.<br><br>For now I am using int[2048][20] but it could be tuned ...<br>
<br>Finally, I figured out several hard-coded values relative to AA (3x3 samples, error level ...) that could be set as rendering hints. For example I would like to tune the number of samples to 8x8 or 2x2 ... depending on the use case. <br>
<br>I expect to send an alpha version of my patch to illustrate my talks.<br><br><div class="gmail_quote">2013/3/30 Jim Graham <span dir="ltr"><<a href="mailto:james.graham@oracle.com" target="_blank">james.graham@oracle.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Other thoughts - using chained buckets of edges instead of one single long list.  It would be easier to keep a pool of buckets (each holding, say, 256 edges?) than a "one-size-fits-all" pool of arrays.  Then all you have to do is keep high water marks on the number of simultaneously used buckets in order to tune the cache for a given application.<br>

<br>
It would make the code that manages "pointers" to edges a little more complicated, though...<br></blockquote><div><br>Good idea, but maybe difficult for me to implement. As I said, this array may be less a problem than rowAARLE. <br>
<br>Of course, I need some "real life" tests to be able to perform better diagnostics: maybe I could add some "instrumentations" / statistics to gather while running in order to tune Pisces automatically depending on the user work load.<br>
<br>Regards,<br>Laurent<br><div><div class="h5">
<br>
On 3/29/2013 6:53 AM, Laurent Bourgès wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Phil,<br>
<br>
I agree it is a complex issue to improve memory usage while maintaining<br>
performance at the JDK level: applications can use java2d pisces in very<br>
different contexts: Swing app (client with only EDT thread), server-side<br>
application (multi thread headless) ...<br>
<br>
For the moment, I spent a lot of my time understanding the different<br>
classes in java2d.pisces and analyzing memory usage / performance ... using<br>
J2DBench (all graphics tests).<br>
<br>
In my Swing application, pisces produces a lot of waste (GC) but on server<br>
side, the GC overhead can be more important if several threads use pisces.<br>
<br>
Pisces uses memory differently:<br>
- fixed arrays (dasher, stroker)<br>
- dynamic arrays (edges ...) rowAARLE (very big one for big shapes)<br>
<br>
For the moment I am trying to avoid memory waste (pooling or kept<br>
reference) without any memory constraint (no eviction) but I agree it is an<br>
important aspect for server-side applications.<br>
<br>
To avoid concurrency issues, I use a ThreadLocal context named<br>
RendererContext to keep few temporary arrays (float6 and a BIG rowAARLE<br>
instance) but there is also dynamic IntArrayCache et FloatArrayCache which<br>
have several pools divided in buckets (256, 1024, 4096, 16384, 32768)<br>
containing only few instances.<br>
<br>
To have best performance, I studied pisces code to clear only the used<br>
array parts when recycling or using dirty arrays (only clear<br>
rowAARLE[...][1]).<br>
<br>
I think Andrea's proposal is interesting to maybe put some system<br>
properties to give hints (low memory footprint, use cache or not ...).<br>
<br>
2013/3/28 Phil Race <<a href="mailto:philip.race@oracle.com" target="_blank">philip.race@oracle.com</a>><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Maintaining a pool of objects might be an appropriate thing for an<br>
applications,<br>
but its a lot trickier for the platform as the application's usage pattern<br>
or intent<br>
is largely unknown. Weak references or soft references might be of use but<br>
weak references usually go away even at the next incremental GC and soft<br>
references tend to not go away at all until you run out of heap.<br>
<br>
</blockquote>
<br>
Agreed; for the moment, pool eviction policy is not implemented but kept in<br>
mind.<br>
FYI: each RendererContext (per thread) has its own array pools (not shared)<br>
that could have different caching policies:<br>
For instance, AWT / EDT (repaint) could use a large cache although other<br>
threads do not use array caching at all.<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
You may well be right that always doubling the array size may be too<br>
simplistic,<br>
but it would need some analysis of the code and its usage to see how much<br>
better we can do.<br>
</blockquote>
<br>
<br>
There is two part:<br>
- initial array size for dynamic arrays: difficult to estimate but for now<br>
set to very low capacity (8 / 50 ...) to avoid memory waste for rectangle /<br>
line shapes. In my patch, I have defined MIN_ARRAY_SIZE = 128 (array pool)<br>
to avoid too much resizing as I am doing array recycling.<br>
- grow: I use x4 instead of x2 to avoid array copies.<br>
<br>
Laurent<br>
<br>
<br>
<br>
2013/3/28 Phil Race <<a href="mailto:philip.race@oracle.com" target="_blank">philip.race@oracle.com</a>><br>
<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Maintaining a pool of objects might be an appropriate thing for an<br>
applications,<br>
but its a lot trickier for the platform as the application's usage pattern<br>
or intent<br>
is largely unknown. Weak references or soft references might be of use but<br>
weak references usually go away even at the next incremental GC and soft<br>
references tend to not go away at all until you run out of heap.<br>
<br>
You may well be right that always doubling the array size may be too<br>
simplistic,<br>
but it would need some analysis of the code and its usage to see how much<br>
better we can do.<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Apparently, Arrays.fill is always faster (size in 10 ... 10 000) !<br>
I suspect hotspot to optimize its code and use native functions, isn't<br>
</blockquote>
it ???<br>
<br>
I suppose there is some hotspot magic involved to recognise and intrinsify<br>
this<br>
method, since the source code looks like a plain old for loop.<br>
<br>
-phil.<br>
<br>
<br>
<br>
On 3/26/2013 4:00 AM, Laurent Bourgès wrote:<br>
<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
Dear all,<br>
<br>
First I joined recently the openJDK contributors, and I plan to fix<br>
java2D pisces code in my spare time.<br>
<br>
I have a full time job on Aspro2: <a href="http://www.jmmc.fr/aspro" target="_blank">http://www.jmmc.fr/aspro</a>; it is an<br>
application to prepare astronomical observations at VLTI / CHARA and is<br>
very used in our community (200 users): it provides scientific computations<br>
(observability, model images using complex numbers ...) and zoomable plots<br>
thanks to jFreeChart.<br>
<br>
Aspro2 is known to be very efficient (computation parallelization) and I<br>
am often doing profiling using netbeans profiler or visualVM.<br>
<br>
To fix huge memory usages by java2d.pisces, I started implementing an<br>
efficient ArrayCache (int[] and float[]) (in thread local to concurrency<br>
problems):<br>
- arrays in sizes between 10 and 10000 (more small arrays used than big<br>
ones)<br>
- resizing support (Arrays.copyOf) without wasting arrays<br>
- reentrance i.e. many arrays are used at the same time (java2D Pisces<br>
stroke / dash creates many segments to render)<br>
- GC / Heap friendly ie support cache eviction and avoid consuming too<br>
much memory<br>
<br>
I know object pooling is known to be not efficient with recent VM (GC is<br>
better) but I think it is counter productive to create so many int[] arrays<br>
in java2d.pisces and let the GC remove such wasted memory.<br>
<br>
Does someone have implemented such (open source) array cache (core-libs) ?<br>
Opinions are welcome (but avoid "trolls").<br>
<br></div></div><br><div class="im">
<br></div></blockquote></blockquote></blockquote></div></div>