Darrel Schneider created GEODE-6636:
---------------------------------------
Summary: Buffers.acquireBuffer is not optimal
Key: GEODE-6636
URL: https://issues.apache.org/jira/browse/GEODE-6636
Project: Geode
Issue Type: Improvement
Components: core
Reporter: Darrel Schneider
org.apache.geode.internal.net.Buffers.acquireBuffer takes buffers out of a
ConcurrentLinkedQueue. If the buffer is too small then it adds it back to the
queue and adds it to an IdentityHashMap. The map is just to detect if we have
looped around and found one we added to the map in a previous iteration.
A more efficient way to do this, which will only remove things from the queue
that we will either throw away or use and return later, and which gets rid of
the map, is to use ConcurrentLinkedQueue.remove(Object). You can see an example
of this by looking at: AvailableConnectionManager.EqualsWithPredicate. The
predicate to use with acquireBuffer is that the soft reference is null or that
the capacity of the referenced buffer is large enough. If you remove one
because the reference is null then you need to call remove(Object) again (after
decrementing the correct stat) since all you did was find one that had been
garbage collected. You want to keep the predicate as cheap as possible since it
is called in the "compare-and-set" spin loop. The more you do in the predicate,
the more likely a concurrent thread will take that buffer and you will need to
spin around and try again.
I was surprised when running a benchmark under the profiler to see operations
on this IdentityHashMap show up. The benchmark was doing pr puts of all the
same size so I would have thought all these direct buffers would be the same. I
think it would be worth understanding what sizes of buffers will be requested
by acquireBuffer and how often they will be acquired and returned. If different
sizes is a normal use case then it probably would make sense to have more than
one queue. If we could go to a queue knowing that if it has a buffer in it that
it meets are desired size. The geode off-heap free list implementation does
this and only the largest allocations need to search through a free list that
has items in it that exceed a max size. Every other free list is found quickly
be using the requested size to index an array of free lists, which only contain
items of that size.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)