Optimize space usage of FastThreadLocal (#7861)
Motivation: A FastThreadLocal instance currently occupies 2 slots of InternalThreadLocalMap of every thread. Actually for a FastThreadLocalThread, it does not need to store cleaner flags of FastThreadLocal instances. Besides, using BitSet to store cleaner flags is also better for space usage. Modification: Use BitSet to optimize space usage of FastThreadLocal. Result: Avoid unnecessary slot occupancy. Cleaner flags are now stored into a BitSet.
This commit is contained in:
parent
1b1f7677ac
commit
010dbe3c73
@ -125,11 +125,8 @@ public class FastThreadLocal<V> {
|
||||
|
||||
private final int index;
|
||||
|
||||
private final int cleanerFlagIndex;
|
||||
|
||||
public FastThreadLocal() {
|
||||
index = InternalThreadLocalMap.nextVariableIndex();
|
||||
cleanerFlagIndex = InternalThreadLocalMap.nextVariableIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,13 +147,11 @@ public class FastThreadLocal<V> {
|
||||
|
||||
private void registerCleaner(final InternalThreadLocalMap threadLocalMap) {
|
||||
Thread current = Thread.currentThread();
|
||||
if (FastThreadLocalThread.willCleanupFastThreadLocals(current) ||
|
||||
threadLocalMap.indexedVariable(cleanerFlagIndex) != InternalThreadLocalMap.UNSET) {
|
||||
if (FastThreadLocalThread.willCleanupFastThreadLocals(current) || threadLocalMap.isCleanerFlagSet(index)) {
|
||||
return;
|
||||
}
|
||||
// removeIndexedVariable(cleanerFlagIndex) isn't necessary because the finally cleanup is tied to the lifetime
|
||||
// of the thread, and this Object will be discarded if the associated thread is GCed.
|
||||
threadLocalMap.setIndexedVariable(cleanerFlagIndex, Boolean.TRUE);
|
||||
|
||||
threadLocalMap.setCleanerFlag(index);
|
||||
|
||||
// We will need to ensure we will trigger remove(InternalThreadLocalMap) so everything will be released
|
||||
// and FastThreadLocal.onRemoval(...) will be called.
|
||||
|
@ -26,6 +26,7 @@ import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
@ -45,6 +46,8 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
||||
|
||||
public static final Object UNSET = new Object();
|
||||
|
||||
private BitSet cleanerFlags;
|
||||
|
||||
static {
|
||||
STRING_BUILDER_INITIAL_SIZE =
|
||||
SystemPropertyUtil.getInt("io.netty.threadLocalMap.stringBuilder.initialSize", 1024);
|
||||
@ -331,4 +334,15 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
||||
Object[] lookup = indexedVariables;
|
||||
return index < lookup.length && lookup[index] != UNSET;
|
||||
}
|
||||
|
||||
public boolean isCleanerFlagSet(int index) {
|
||||
return cleanerFlags != null && cleanerFlags.get(index);
|
||||
}
|
||||
|
||||
public void setCleanerFlag(int index) {
|
||||
if (cleanerFlags == null) {
|
||||
cleanerFlags = new BitSet();
|
||||
}
|
||||
cleanerFlags.set(index);
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class FastThreadLocalTest {
|
||||
|
||||
// Initialize a thread-local variable.
|
||||
assertThat(var.get(), is(nullValue()));
|
||||
assertThat(FastThreadLocal.size(), is(2));
|
||||
assertThat(FastThreadLocal.size(), is(1));
|
||||
|
||||
// And then remove it.
|
||||
FastThreadLocal.removeAll();
|
||||
|
Loading…
x
Reference in New Issue
Block a user