Enforce ratioMask also for WeakOrderQueue (#9727)
Motivation: At the moment we only enfore ratioMask for the Stack which means that we only guard against recycle burts when recycled from the same Thread. We should also enforce the ratioMask in the WeakOrderQueue so we also guard against the bursts when recycle from other threads. Modifications: - Keep counter in WeakOrderQueue to enforce ratioMask as well - Adjust unit test Result: Better guard against recycle bursts which could pollute the heap unnecessary.
This commit is contained in:
parent
cedfa41f3f
commit
71860e5b94
@ -306,10 +306,13 @@ public abstract class Recycler<T> {
|
||||
// pointer to another queue of delayed items for the same stack
|
||||
private WeakOrderQueue next;
|
||||
private final int id = ID_GENERATOR.getAndIncrement();
|
||||
private final int ratioMask;
|
||||
private int handleRecycleCount;
|
||||
|
||||
private WeakOrderQueue() {
|
||||
super(null);
|
||||
head = new Head(null);
|
||||
ratioMask = 0;
|
||||
}
|
||||
|
||||
private WeakOrderQueue(Stack<?> stack, Thread thread) {
|
||||
@ -321,6 +324,7 @@ public abstract class Recycler<T> {
|
||||
// Stack itself GCed.
|
||||
head = new Head(stack.availableSharedCapacity);
|
||||
head.link = tail;
|
||||
ratioMask = stack.ratioMask;
|
||||
}
|
||||
|
||||
private static WeakOrderQueue newQueue(Stack<?> stack, Thread thread) {
|
||||
@ -358,6 +362,14 @@ public abstract class Recycler<T> {
|
||||
void add(DefaultHandle<?> handle) {
|
||||
handle.lastRecycledId = id;
|
||||
|
||||
// While we also enforce the recycling ratio one we transfer objects from the WeakOrderQueue to the Stack
|
||||
// we better should enforce it as well early. Missing to do so may let the WeakOrderQueue grow very fast
|
||||
// without control if the Stack
|
||||
if ((++handleRecycleCount & ratioMask) != 0) {
|
||||
// Drop the item to prevent recycling to aggressive.
|
||||
return;
|
||||
}
|
||||
|
||||
Link tail = this.tail;
|
||||
int writeIndex;
|
||||
if ((writeIndex = tail.get()) == LINK_CAPACITY) {
|
||||
@ -640,6 +652,7 @@ public abstract class Recycler<T> {
|
||||
// We don't support recycling across threads and should just drop the item on the floor.
|
||||
return;
|
||||
}
|
||||
|
||||
// we don't want to have a ref to the queue as the value in our weak map
|
||||
// so we null it out; to ensure there are no races with restoring it later
|
||||
// we impose a memory ordering here (no-op on x86)
|
||||
|
@ -174,6 +174,7 @@ public class RecyclerTest {
|
||||
|
||||
final HandledObject o = recycler.get();
|
||||
final HandledObject o2 = recycler.get();
|
||||
|
||||
final Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -184,8 +185,9 @@ public class RecyclerTest {
|
||||
thread.start();
|
||||
thread.join();
|
||||
|
||||
assertSame(recycler.get(), o);
|
||||
assertNotSame(recycler.get(), o2);
|
||||
// As we use a ratioMask of 2 we should see o2 as the first object that could recycled from a different thread.
|
||||
assertSame(recycler.get(), o2);
|
||||
assertNotSame(recycler.get(), o);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user