Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use entry.unguardedRecycle() instead of entry.recycle() in method MemoryRegionCache.freeEntry(...) #13727

Closed
wants to merge 1 commit into from

Conversation

laosijikaichele
Copy link
Contributor

@laosijikaichele laosijikaichele commented Dec 13, 2023

Motivation:

This is related to #13220, I think we should use entry.unguardedRecycle() instead of entry.recycle() in method MemoryRegionCache.freeEntry(...), to make the 'recycle' operation cheaper.

In current implementation, the entry is either recycled by the thread which created it, or by the thread which consumed the 'Mpsc' MemoryRegionCache.queue queue, if the two threads are not the same, then the two threads are mutually exclusive to recycle the entry.
Every thread gets the entry from the threadLocal, so there should be no concurrency/visible problem.

Modification:

Use entry.unguardedRecycle() instead of entry.recycle() in method MemoryRegionCache.freeEntry(...).

Result:

Make the 'recycle' operation cheaper.

@@ -438,7 +438,7 @@ private void freeEntry(Entry entry, boolean finalizer) {
if (!finalizer) {
// recycle now so PoolChunk can be GC'ed. This will only be done if this is not freed because of
// a finalizer.
entry.recycle();
entry.unguardedRecycle();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correctly always previously used by another (atomic) operation that shield it?
Given that the previous one isn't visible is not easy to tell by reading that snippet of code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franz1981 It seems this snippet of code is always called by the thread which consumes the MemoryRegionCache.queue, and the MemoryRegionCache.queue is a Mpsc queue, so I think it's safe to use entry.unguardedRecycle() here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who consumes the MemoryRegionCache.queue

who consume or offer vs it?
Because consumption is (although it is an impl detail of JMM, actually, so take it with the grain of salt):

slot read item 
loadload + loadstore (load-acquire the slot element)
storestore + loadstore (store-release the null value in the slot element)
set slot to null
// and potentially
storestore + loadstore (store-release the entry)
unguarded release

which should end up to

STATE_UPDATER.lazySet(this, STATE_AVAILABLE);

In short, the ordering it's not a problem, concurrency can be, but given that it's a single-consumer queue I see no harm, although it's brittle because it's not immediately visible in the method signature.

Did you have any benchmark (or micro) which show that as an hot spot we care about?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@franz1981
The thread which releases byteBuf offer the MemoryRegionCache.queue.

I have not done the benchmark yet.

I noticed this because there is a similar entry.unguardedRecycle() calling in method PoolThreadCache.MemoryRegionCache.allocate:

Which has the similar logic with this PR's change, so I think it's better to make both 'recycle' operations calling the same entry.unguardedRecycle() method.

In current implementation, the entry is either recycled by the thread which created it, or by the thread which consumed the Mpsc queue, if the two threads are not the same, then the two threads are mutually exclusive to recycle the entry.
Every thread gets the entry from threadLocal, so there should be no concurrency problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should first really benchmark and see if this makes any difference

@normanmaurer
Copy link
Member

Let me close this for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants