One thing I'd like to hear from Joe or Phil or Dalibor is if it is OK for us to check in the current version to the graphics-rasterizer-dev java.net repo as long as we resolve this before we push to the client or master repos? I'd like to get Laurent's current work in so that we can start tweaking it and right now it is a huge webrev to slog through for even simple changes. I'm guessing that since every changeset in the master repo requires a bug id that we'll end up collapsing this initial push and a number of subsequent tweaks into a single changeset for the eventual integration so any files that we obsolete during that process may never make it to the main repos.

Or do we want "due diligence" of contributing sources on any change that gets hosted on any repo (even sandboxes) on java.net?

                        ...jim

On 3/27/15 2:19 AM, Laurent Bourgès wrote:
Hi Phil & Joe,

Thanks for your opinions, but let me explain the impact of ceil(float)
in the Marlin renderer:
- for every line, 2 ceil calls are performed => depends on the shape
complexity
- for every rendering pass, typically every 32 pixel stride, 4 ceil
calls are performed => depends on the shape's vertical coverage

=> In my benchmarks, I experienced that the Math.ceil(float) method is
called million times (I can gather numbers if you want).

As I want to achieve the best possible performance, I used that "trick"
to have a faster (but accurate enough) alternative which gives in my
MapBench benchmarks ~ 3% performance.

I advocate 3% is small but it will depend on the drawing complexity: the
more complex your shapes are, the bigger is the speedup.

    Since JDK 7 the JDK has used a pure-Java implementation of floor and
    ceil:

         6908131 Pure Java implementations of StrictMath.floor(double) &
    StrictMath.ceil(doublele)
    https://bugs.openjdk.java.net/__browse/JDK-6908131
    <https://bugs.openjdk.java.net/browse/JDK-6908131>


Thanks for the pointer, I will look at the StrictMath.ceil code to see
if I can optimize it for general use (any kind of inputs).

    So in this case I would suggest we follow the implications of
    Knuth's observation that "premature optimization is the root of all
    evil" and only look to further speed up floor / ceil if there is
    some appreciable performance problem  with them today as shown in
    benchmarks, etc.


I know that principle, but I am pragmatic: ceil(float) has a noticeable
impact on rendering performance according to my benchmarks which are
based on real map use cases (geoserver).

    On 3/25/2015 2:44 PM, Phil Race wrote:

        FastMath:
        
http://cr.openjdk.java.net/~__lbourges/marlin/marlin.3/src/__java.desktop/share/classes/__sun/java2d/marlin/FastMath.__java.html
        
<http://cr.openjdk.java.net/~lbourges/marlin/marlin.3/src/java.desktop/share/classes/sun/java2d/marlin/FastMath.java.html>


        says its from here :
        http://www.java-gaming.org/__index.php?topic=24194.0
        <http://www.java-gaming.org/index.php?topic=24194.0>

        but that in turn may be from somewhere else unknown ..

        Aside from the provenance of the code, and even though its a
        'trick' rather than a body of code,
        other options are preferable, so it might be interesting to get
        Joe's input on what other options
        there are that maintain correctness and give better performance
        - I assume this gives
        a measurable benefit ?


1. I agree that trick comes from a java forum, but it is more an idea
that a body of code:
     ceil = upper_bound_integer - (int) ( upper_bound_double - x_float)

As I said, the code could be rewritten to ensure values are positive so
a integer cast is enough. Of course, the floating-point precision can
have tricky side-effects (and also overflow / NaN handling).

2. Yes, it gives speedup: here are the synthetic benchmark results with
/ without the trick enabled [-Dsun.java2d.renderer.useFastMath=true|false] :

==> marlin_TL_Tile_1.log <==

Tests    27    9    9    9
Threads    4    1    2    4
Pct95    132.498    131.176    132.641    133.677

==> marlin_TL_Tile_noFM_3.log <==

Tests    27    9    9    9
Threads    4    1    2    4
Pct95    135.669    134.989    135.541    136.477


        Is the limitation on the input range an issue ? There's no test
        here for that, and
        correctness-wise this does seem to break down if the input is NaN.


1. In Pisces / Marlin, ceil is used in a specific context to upper
integer values:

     private void addLine(float x1, float y1, float x2, float y2) {
...
         /* convert subpixel coordinates (float) into pixel positions
(int) */
         // upper integer (inclusive)

         final int firstCrossing = Math.max(FastMath.ceil(y1),
_boundsMinY);

         // upper integer (exclusive ?)
         final int lastCrossing  = Math.min(FastMath.ceil(y2),
_boundsMaxY);


     boolean endRendering() {
...

         /* bounds as inclusive intervals */
         final int spminX = Math.max(Math.ceil(edgeMinX), boundsMinX);
         final int spmaxX = Math.min(Math.ceil(edgeMaxX), boundsMaxX - 1);
         final int spminY = Math.max(Math.ceil(edgeMinY), boundsMinY);
         final int spmaxY = Math.min(Math.ceil(edgeMaxY), boundsMaxY - 1);

However, to improve the coordinate rounding arround subpixel centers, it
should be rewritten (as jim pointed out):
ceil(float) => ceil(x - 0.5f) or floor(x + 0.5f)

Anway, the returned values are then clamped into [min | max] ranges.

Do you know any faster alternative to do such rounding + boundary clipping ?


2. I agree it does not handle overflow or NaN but that is a real problem
with Pisces in general: I think it should be tested and fixed in a
second step.

For example, I you draw a vertical or horizontal line with x / y = NaN
then it fails !
Moreover, as coordinates are multiplied by 8, it can overflow float and
integer maximum values !!

I think clipping should be implemented to ensure all coordinates belongs
to the clip boundaries.


To conclude, I propose to remove the FastMath utility class now and
later use a new Renderer utility method to perform both rounding and
bound checks at the same time with your help.

Cheers,
Laurent

Reply via email to