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 index;
|
||||||
|
|
||||||
private final int cleanerFlagIndex;
|
|
||||||
|
|
||||||
public FastThreadLocal() {
|
public FastThreadLocal() {
|
||||||
index = InternalThreadLocalMap.nextVariableIndex();
|
index = InternalThreadLocalMap.nextVariableIndex();
|
||||||
cleanerFlagIndex = InternalThreadLocalMap.nextVariableIndex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,13 +147,11 @@ public class FastThreadLocal<V> {
|
|||||||
|
|
||||||
private void registerCleaner(final InternalThreadLocalMap threadLocalMap) {
|
private void registerCleaner(final InternalThreadLocalMap threadLocalMap) {
|
||||||
Thread current = Thread.currentThread();
|
Thread current = Thread.currentThread();
|
||||||
if (FastThreadLocalThread.willCleanupFastThreadLocals(current) ||
|
if (FastThreadLocalThread.willCleanupFastThreadLocals(current) || threadLocalMap.isCleanerFlagSet(index)) {
|
||||||
threadLocalMap.indexedVariable(cleanerFlagIndex) != InternalThreadLocalMap.UNSET) {
|
|
||||||
return;
|
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.setCleanerFlag(index);
|
||||||
threadLocalMap.setIndexedVariable(cleanerFlagIndex, Boolean.TRUE);
|
|
||||||
|
|
||||||
// We will need to ensure we will trigger remove(InternalThreadLocalMap) so everything will be released
|
// We will need to ensure we will trigger remove(InternalThreadLocalMap) so everything will be released
|
||||||
// and FastThreadLocal.onRemoval(...) will be called.
|
// and FastThreadLocal.onRemoval(...) will be called.
|
||||||
|
@ -26,6 +26,7 @@ import java.nio.charset.CharsetDecoder;
|
|||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
@ -45,6 +46,8 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
|||||||
|
|
||||||
public static final Object UNSET = new Object();
|
public static final Object UNSET = new Object();
|
||||||
|
|
||||||
|
private BitSet cleanerFlags;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
STRING_BUILDER_INITIAL_SIZE =
|
STRING_BUILDER_INITIAL_SIZE =
|
||||||
SystemPropertyUtil.getInt("io.netty.threadLocalMap.stringBuilder.initialSize", 1024);
|
SystemPropertyUtil.getInt("io.netty.threadLocalMap.stringBuilder.initialSize", 1024);
|
||||||
@ -331,4 +334,15 @@ public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap
|
|||||||
Object[] lookup = indexedVariables;
|
Object[] lookup = indexedVariables;
|
||||||
return index < lookup.length && lookup[index] != UNSET;
|
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.
|
// Initialize a thread-local variable.
|
||||||
assertThat(var.get(), is(nullValue()));
|
assertThat(var.get(), is(nullValue()));
|
||||||
assertThat(FastThreadLocal.size(), is(2));
|
assertThat(FastThreadLocal.size(), is(1));
|
||||||
|
|
||||||
// And then remove it.
|
// And then remove it.
|
||||||
FastThreadLocal.removeAll();
|
FastThreadLocal.removeAll();
|
||||||
|
Loading…
Reference in New Issue
Block a user