javafx.scene.shape.Path (memory) inefficient PathElements
Jose Martinez
jmartine_1026 at yahoo.com
Thu Jul 27 11:41:52 UTC 2017
Just curious, did this make it to the 8u144 release? If not, any idea which release (or when) we can expect it?
Thank youjose
On Wednesday, May 24, 2017 08:38:41 PM EDT, Jim Graham <james.graham at oracle.com> wrote:
Thanks Tom, I've already posted a patch for 8180938 (lazy property creation). Check it out and let me know how it
performs for you.
I have a couple of changes to make to it (and an independent memory usage test to write) before I send it out for formal
review...
...jim
On 5/24/17 3:42 AM, Tom Schindl wrote:
> Hi,
>
> I created:
> - https://bugs.openjdk.java.net/browse/JDK-8180935
> - https://bugs.openjdk.java.net/browse/JDK-8180938
>
> I'll work on a showcase to find out how much memory one can save.
>
> Tom
>
> On 04.05.17 23:33, Jim Graham wrote:
>> Hi Tom,
>>
>> Those look like good suggestions. I would file bugs in JBS and create
>> them separately:
>>
>> - Bug for lazy property creation in path elements
>> - Feature request for lower-memory paths
>>
>> Did you benchmark how much the lazy properties, on their own, would save
>> your application?
>>
>> ...jim
>>
>> On 5/4/17 2:22 PM, Tom Schindl wrote:
>>> Hi,
>>>
>>> We are currently working on a PDF-Rendering library in JavaFX and we
>>> need to draw glyphs using the JavaFX Path API (there are multiple
>>> reasons why we don't use the Text-Node and or Canvas).
>>>
>>> When drawing a page full of Text this means that we have a Path-Object
>>> with gazillions of MoveTo and CubicCurveTo elements who sum up to 30MB
>>> just to represent them in the SG because PathElements store their
>>> information in properties and forcefully intialize them in their
>>> constructor.
>>>
>>> The only public API to work around this problem is to construct a
>>> StringBuffer and use SVGPath which means:
>>> * it takes time to construct the SVG-Path-String
>>> * it takes time to parse the SVG-Path-String in JavaFX
>>>
>>> As an experiment (and because we are still on Java8 we can easily do
>>> that) was that we created our own Shape-Subclass who:
>>> * uses floats (there's no reason to use double in the SG when the
>>> backing API - Path2D - is float based)
>>> * passes the floats directly to the Path2D/NGPath API
>>>
>>> Guess what: We now need 2.5MB / page which means 27.5MB is the overhead
>>> added by the current Path-API - ouch!
>>>
>>> I think a fairly low hanging memory optimization for the PathElement
>>> would be to create properties lazy (only if someone access the property).
>>>
>>> For MoveTo this would mean the following minimal change (eg for the
>>> x-value):
>>>
>>> private DoubleProperty x;
>>> private double _x;
>>>
>>> public final void setX(double value) {
>>> if (x != null) {
>>> xProperty().set(value);
>>> } else {
>>> _x = value;
>>> u();
>>> }
>>> }
>>>
>>> public final double getX() {
>>> return x == null ? _x : x.get();
>>> }
>>>
>>> public final DoubleProperty xProperty() {
>>> if (x == null) {
>>> x = new DoublePropertyBase(_x) {
>>>
>>> @Override
>>> public void invalidated() {
>>> u();
>>> }
>>>
>>> @Override
>>> public Object getBean() {
>>> return MoveTo.this;
>>> }
>>>
>>> @Override
>>> public String getName() {
>>> return "x";
>>> }
>>> };
>>> }
>>> return x;
>>> }
>>>
>>> I guess 99% of the code out there never access the Property so the small
>>> footprint added by the primitive field is justifiable.
>>>
>>> This still has the overhead of all the needless PathElement objects
>>> hanging around so another idea is to have a 3rd SG-Path-Type who
>>> strictly uses the float-Primitives with a similar API to Path2D (in fact
>>> it only acts as a public API to Path2D).
>>>
>>> Thoughts?
>>>
>>> Tom
>>>
>
>
More information about the openjfx-dev
mailing list