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 >> -- Thomas Schindl, CTO BestSolution.at EDV Systemhaus GmbH Eduard-Bodem-Gasse 5-7, A-6020 Innsbruck http://www.bestsolution.at/ Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck