hypfvieh / dbus-java

Improved version of java DBus library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/)
https://hypfvieh.github.io/dbus-java/
MIT License
185 stars 73 forks source link

Variant memory allocations #184

Closed ghost closed 2 years ago

ghost commented 2 years ago

After resolving #182, instances of Variant now dominate memory profiling, as shown in the screenshot:

Variant

The GC profiling shows:

GC

Is there anything that can be done to reduce the number of Variant instances created? There appears to be a 1:1 relationship with a Message instance.

hypfvieh commented 2 years ago

That will not be easy to fix (if it is fixable at all). A Variants array is used in the header of each message (DBus Spec) and this header will be read first when a message is transformed to a Java object.

So the same code as for reading anything else on the message is used to get that header information. This is good in terms of re-using the code, but bad because for the header map in the message only the contents of the variant is stored. Therefore for each messages an arbitrary amount of variants is created, the containing value is stored and the variant itself will be ignored (therefore are eligible for garbage collection).

I'll take a closer look to that, maybe I can refactor some points to get rid of the overhead of creating variant objects.

hypfvieh commented 2 years ago

Alright, after hours of investigating, optimizing and refactoring I added a new branch with my changes.

The change will use a new method to read the header for each message which will not create the Variant objects. Instead it will read the data object of the Variant directly and return this in the Object[] instead of the Variant. Before the change, Object[] read from message contained Byte + Variant, now it contains Byte + Object. This allows storing the Object directly in the header map (which is Map<Byte, Object>) of the message without unwrapping the Variant first.

ghost commented 2 years ago

Thank you! The Variant instances are now gone in the small demo program I wrote:

dbus-no-variant

In our main application, the Message objects promote to Gen 2, which decreases stress on the GC. Decreasing the GC stress reduces the probability of stop-the-world pauses. We have tight timing constraints where stop-the-world events can cause buffer overruns, resulting in dropped data.

Preliminary application tests show significant improvements: there are far fewer stop-the-world events now. We're basically back to pre-D-Bus integration performance. Much appreciated.