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

SignalTuple memory allocations #182

Closed ghost closed 2 years ago

ghost commented 2 years ago

The following screenshot shows the memory allocations against the Gen 1 GC:

signal-tuple-1

The method getAllPossibleTuples is creating 19 instances of SignalTuple for every message. Our application receives 64 messages per second, resulting in 1,216 objects per second. This stresses the GC.

https://github.com/hypfvieh/dbus-java/blob/89ea49d2c1a58e012b291c6794a4fa1e5b4d7157/dbus-java-core/src/main/java/org/freedesktop/dbus/SignalTuple.java#L63

When the GC runs, it needs to free 600 to 700 kB of SignalTuple instances from memory.

Here's a screenshot of the GC sawtooth:

dbus-heap

Is it possible to cache these so that they are only created once?

hypfvieh commented 2 years ago

Creating the signal tuples all the time is really a bad idea.

The purpose for all of this is to support generic signal handlers. Generic means you specify a handler which will be called when only a part of the signal is matched (e.g. only source and target are required for the handler to be notified). So to notify all possibly installed generic handlers all variants of signal tuple are required because you never know how generic the handler is.

Caching may be an option, also I don't really like that. Creating a cache also requires to maintain the cache, remove old entries (when do that?), create a proper way to lookup the tuples in cache etc.

I'm currently thinking of a solution which does not require the SignalTuple in all possible flavours. The major problem is: the tuples are currently used to lookup the handler in a ConcurrentHashMap. So I need to find some suitable replacement for this operation....

hypfvieh commented 2 years ago

So I took some time and changed the signal handling a bit. Goal was to get rid of the SignalTuple and to stop creating many objects to find a suitable map key. You may try the changes in branch signal-handling-improvements. My changes are described in the commit comment.

ghost commented 2 years ago

Smashing! The SignalTuple is no longer showing up during memory profiling:

dbus-variant

The GC sawtooth pattern still shows a lot of churn:

dbus-monitor-variant

The Variant class is now dominating. This is quite an improvement. From what I can see, the Variant has a 1:1 relationship with a Message. I'm not sure if there's a way to eliminate the Variant instances. I'll open a new ticket.

Closing this ticket as fixed.

Thank you!