Shadow Fields vs. Property Accessor Interface Round 2
If you guys haven’t noticed a (light-hearted) showdown between Dirk Lemmerman and me, let me quickly mention how we got to this point. For starters, Dirk created a JavaFX tip 23: “Save Memory Shadow Fields for Properties” to help application developers save memory when using JavaFX Properties. Pretty impressive knowing that you can save memory when objects aren’t needing to use JavaFX Property objects.
While looking at the code I couldn’t help but notice boilerplate code that drove me bonkers, so I decided to make a simple API that also took into account the interesting Shadow Fields pattern used by Dirk’s example. The API I created aka Property Accessor Interface comprises of default methods that easily allows developers to implement the interface as opposed to extending an abstract class to avoid Java’s single inheritance rule. To see the Property Accessor interface code I blog about it here. To my surprise Dirk created yet another blog entry to benchmark all three approaches. Below is the chronological order of the blog posts thus far if you are keeping up with all the fun.
- Save Memory Shadow Fields for Properties by Dirk Lemmerman
Introducing the concept of Shadow Fields - JavaFX Tips to Save Memory! Shadow Fields for Properties and Observables by Carl Dea
My attempt to save memory and reduce boilerplate code. - Shadow Fields vs. Property Accessor Interface by Dirk Temmerman
A benchmark application to test the three approaches of objects having properties and raw datatypes for fields. - Shadow Fields vs. Property Accessor Interface Round 2 by Carl Dea
A revisit of the Property Accessor Interface to reduce the memory usage by centralizing a map of values.
As it turns out my implementation was the worst of the three even with the bloated object with already instantiated property fields according to post #3 above. Because I rushed into things and didn’t know the issue until Dirk’s post #3 above. Well, I’m not ready to wave the white flag and besides I still have a few tricks up my sleeve.
Next, you will get to see what I did to reduce the memory usage of the Property Accessor interface strategy. To see the code changes please see the code at the Github here. The only change I made was centralizing the Map containing the values. As you can see below the memory is much lower compared to Dirk’s post #3 above. However, event though I didn’t beat Dirk’s implementation using shadow fields I did slightly better than the standard object approach.
An updated Property Accessor Interface implementation using a centralized map.
Conclusion
Although I’ve only made a simple change by removing the hash maps from every object and centralizing all values to a single map the Property Accessor interface still didn’t trim memory as low as the Shadow fields technique. I may explore other techniques such as weak references or take a look into memory mapped files. I doubt I can reduce things any further, but I believe a relatively small to medium application could use the Property Accessor interface to rapidly build apps. They (developers) could use proper pagination to avoid large lists. One last idea would be to create an annotation that could even reduce the boiler plate code.
Let me know ow what you think? Any suggestions?
Reference: | Shadow Fields vs. Property Accessor Interface Round 2 from our JCG partner Carl Dea at the Carl’s FX Blog blog. |
When you use arrays instead of the heavy HashMap you get memory usage of 144 MB (and with property beans 864 MB). Also the access time is better than with the HashMap. ———- package com.dlsc.profiling; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; import javafx.beans.property.Property; import javafx.collections.FXCollections; import javafx.collections.ObservableList; /** * Provide default methods to support the similar capability of the shadow fields pattern. To save * memory object values don’t have to be wrapped into a Property object when using getters and * setters, however when calling property type methods values will be wrapped into a property * object. * *… Read more »