[Performance] java.awt.geom.Area#intersect should do basic bounds checking prior to calculating the intersection

Jeremy Wood mickleness at gmail.com
Sun Feb 25 21:50:30 UTC 2024


Taylor,

 > Is there a reason why `intersect` doesn't look something like 
[example]

I think (?) there isn’t an appetite in this group to improve the Area 
class. I agree there’s a lot of room for improvement in that class, but 
I’m a relative outsider (lurker) to this group.

(I proposed a simpler optimization 
<https://mail.openjdk.org/pipermail/client-libs-dev/2022-February.txt> 
to the Area class a few years ago, and it didn’t generate any 
enthusiasm.)

I like the Area class, but it’s definitely caused (avoidable) 
performance bottlenecks over the years.

I also started a project <https://github.com/mickleness/outline/> a few 
years ago that includes your proposed optimization and several others. 
Given a variety of shapes it can perform clipping operations in 10% of 
the time 
<https://github.com/mickleness/outline/blob/master/Clipping%20Shapes%20Output.log> 
the Area takes. And it can perform additions in 56% of the time 
<https://github.com/mickleness/outline/blob/master/Adding%20Shapes%20For%20Outline%20Output.log>. 
Unfortunately: I haven’t worked on it in over a year. It probably needs 
more attention. If anyone wants to discuss that off-list please feel 
free to email me.

(And if any contributor on this list wants to help sponsor/review work 
for openjdk Area optimizations: please let us know! I’m happy to help.)

Regards,
  - Jeremy

------ Original Message ------
>From "Taylor Smock" <taylor.smock at kaart.com>
To client-libs-dev at openjdk.org
Date 2/13/24, 2:31:52 PM
Subject [Performance] java.awt.geom.Area#intersect should do basic 
bounds checking prior to calculating the intersection

>While I was investigating a way to improve performance in JOSM (see 
>https://josm.openstreetmap.de/ticket/23472 ), I saw that 
>java.awt.geom.Area#intersect was taking a disproportionate amount of 
>CPU cycles.
>
>I was able to decrease the amount of time spent in `intersect` by doing 
>bounds intersection checks prior to calling `intersect`.
>
>Is there a reason why `intersect` doesn't look something like
>
>     public void intersect(Area rhs) {
>         final var lhsBounds = this.getCachedBounds();
>         final var rhsBounds = rhs.getCachedBounds();
>         if (!lhsBounds.intersects(rhsBounds) || 
>!this.intersects(rhsBounds) || !rhs.intersects(lhsBounds)) {
>             curves = EmptyCurves;
>         } else {
>             curves = new AreaOp.IntOp().calculate(this.curves, 
>rhs.curves);
>         }
>         invalidateBounds();
>     }
>
>My assumption is that it wasn't a method that has been extensively 
>profiled, but it is entirely possible that there is something I don't 
>know.
>
>
>
>For reference, the bounds checking I did outside of the JDK looked like 
>this (simplified -- see link above for actual code):
>
>     public static Area calculateIntersection(Area lhs, Area rhs) {
>         final Rectangle lhsBounds = lhs.getBounds2d();
>         final Rectangle rhsBounds = rhs.getBounds2d();
>         if (!lhsBounds.intersects(rhsBounds) && 
>!lhs.intersects(rhsBounds) && !rhs.intersects(lhsBounds)) {
>             return new Area();
>         }
>         return lhs.intersect(rhs);
>     }
>
>
>
>For my specific use case, this lead to the following performance 
>improvements in my test workload (CPU and memory allocations as 
>measured by IntelliJ IDEA's profiler for the calling method):
>
>
>CPUMemory AllocationsTotal Validator Time
>No patch 522,778ms 54.13 GB ~840s
>Patch 22,581ms 1.13 GB ~210s
>Difference -500,197ms -53 GB -630s
>Difference % -95.7% -97.9% -77.7%
>
>Thanks,
>
>Taylor
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/client-libs-dev/attachments/20240225/ae0ad92d/attachment.htm>


More information about the client-libs-dev mailing list