[infinispan-dev] Cost of inheritance
Sanne Grinovero
sanne at infinispan.org
Thu Nov 14 16:18:08 EST 2013
In a particular benchmark I'm running, the bottleneck of my system
seems to be the object allocation rate.
More specifically, in just some minutes I've got about 55GB allocated
just of instances of SingleKeyNonTxInvocationContext
(yes I literally mean GigaBytes)
and 45GB of org.infinispan.commands.read.GetKeyValueCommand.
To be clear: these high amounts are caused only by the "shallow" class
instance of these two types, not counting key nor value sizes being
actually moved into/out Infinispan.
Of course it means we're talking about many of these instances, but
also the size of each of them matters, so I've been taking a look at
their definitions.
Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.
# org.infinispan.context.SingleKeyNonTxInvocationContext
offset size type description
0 12 (assumed to be the object header + first
field alignment)
12 1 byte AbstractInvocationContext.contextFlags
13 3 (alignment/padding gap)
16 4 Address AbstractInvocationContext.origin
20 4 WeakReference AbstractInvocationContext.classLoader
24 1 boolean SingleKeyNonTxInvocationContext.isOriginLocal
25 1 boolean SingleKeyNonTxInvocationContext.isLocked
26 2 (alignment/padding gap)
28 4 Object SingleKeyNonTxInvocationContext.key
32 4 CacheEntry SingleKeyNonTxInvocationContext.cacheEntry
36 4 (loss due to the next object alignment)
40 (object boundary, size estimate)
I notice two things in here:
a) we could refactor maybe some code to have less fields in such a
hot allocated type
b) Lots of space is being wasted in padding!
If you count the bytes lost because of the various alignment rules: 9
That's almost 25%, about 13GB of used memory!
Why are there two separate object alignment gaps? That's because the
fields of the parent class need to be grouped, then the child class's
fields are aligned after it.
In other words, if I move the fields from the parent class to the
bottom class I get:
org.infinispan.context.SingleKeyNonTxInvocationContext
offset size type description
0 12 (assumed to be the object header + first
field alignment)
12 1 byte SingleKeyNonTxInvocationContext.contextFlags
13 1 boolean SingleKeyNonTxInvocationContext.isOriginLocal
14 1 boolean SingleKeyNonTxInvocationContext.isLocked
15 1 (alignment/padding gap)
16 4 Address SingleKeyNonTxInvocationContext.origin
20 4 ClassLoader SingleKeyNonTxInvocationContext.classLoader
24 4 Object SingleKeyNonTxInvocationContext.key
28 4 CacheEntry SingleKeyNonTxInvocationContext.cacheEntry
32 (object boundary, size estimate)
which recovers 20% ..
Looking forward to see simpler class hierarchies in the code ;-)
Sanne
More information about the infinispan-dev
mailing list