Darrel Schneider created GEODE-9497:
---------------------------------------

             Summary: RedisHash and RedisSortedSet both use a hashMap that uses 
more memory than it needs to
                 Key: GEODE-9497
                 URL: https://issues.apache.org/jira/browse/GEODE-9497
             Project: Geode
          Issue Type: Bug
          Components: redis
            Reporter: Darrel Schneider


Both RedisHash and RedisSortedSet have an instance of  
SizeableObject2ObjectOpenCustomHashMapWithCursor which can end up keeping some 
objects alive that are not really needed. The memory used by these object is 
currently not kept track of by geode's getSizeInBytes implementation. 
The objects referenced by these three fields are the problem:
# *entries* an instance of 
it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap.MapEntrySet
# *keys* an instance of 
it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap.KeySet
# *values* an instance of an anonymous subclass of 
it.unimi.dsi.fastutil.objects.AbstractObjectCollection
        
These fields get lazily initialized when their corresponding method is called. 
Once they are initialized they stay that way forever. The object they reference 
is immutable. Its only field is the implicit reference to its outer class 
instance. Currently it looks like we have redis ops that can end up calling all 
three of these methods in which case these objects would account for over 100 
bytes on a 64-bit jvm.

It is not clear to me why the implementors of Object2ObjectOpenCustomHashMap 
chose to cache this immutable object instead of just creating it every time. 
They have no state to initialize when constructed so one thing we could do is 
override the methods that cache it to either null out the cached field after 
calling the super method, or have the method ignore the super implementation 
and just create and returns an instance without caching. The cache fields 
themselves would be a waste of memory in that case but only 24 bytes (12 with 
compressed oops). To avoid this waste of memory we could just create our own 
subclass of AbstractObject2ObjectMap that does not have these three fields. It 
looks like we might be able to get rid of some other fields (one of them is to 
support null keys which we never use). If we go that direction we should 
probably force byte array keys instead of have a generic parameter and we could 
then get rid of the strategy field.

Another possibility would be for our code that uses the map to only call 
entrySet(), that way one instance would be cached instead of 3. You can always 
get keys and values from the entrySet. Even better would be to add the methods 
we need to our subclass of Object2ObjectOpenCustomHashMap named 
SizeableObject2ObjectOpenCustomHashMapWithCursor. We did this for scan to have 
a stable cursor and we could do it easily for the places we need keys, values, 
or entries. It would be easy to add the foreach style of method directly on our 
subclass and use it in RedisHash. If we do this then we should probably 
override the other methods to throw an exception to prevent someone from 
accidentally using them in the future.




--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to