Why Netty Uses FastThreadLocal Over JDK ThreadLocal: Deep Dive & Code Analysis
This article explains why Netty introduces FastThreadLocal instead of relying on JDK ThreadLocal, detailing its background, core principles, source code structure—including InternalThreadLocalMap, FastThreadLocalThread, and FastThreadLocal implementations—performance implications, resource reclamation mechanisms, and practical usage within Netty’s memory allocation.
1 FastThreadLocal Background and Principle
Netty implements its own FastThreadLocal (ftl) to avoid the hash‑collision overhead of JDK ThreadLocal. Each Java thread has a ThreadLocalMap that uses linear probing; ftl replaces this with an array indexed by a unique int assigned via an AtomicInteger.
When ftl.get() is called, the value is retrieved directly from the array using the stored index, e.g. return array[index].
2 Source Code Analysis
2.1 UnpaddedInternalThreadLocalMap Core Fields
static final ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap = new ThreadLocal<InternalThreadLocalMap>();
static final AtomicInteger nextIndex = new AtomicInteger();
Object[] indexedVariables;The indexedVariables array stores ftl values; nextIndex provides a unique slot for each ftl instance.
2.2 InternalThreadLocalMap
// Marker for unused slots
public static final Object UNSET = new Object();
private BitSet cleanerFlags;</n>The map creates a fixed‑size array (default 32) filled with UNSET and provides indexedVariable(int index) to fetch values.
2.3 FastThreadLocalThread (ftlt)
public class FastThreadLocalThread extends Thread {
private final boolean cleanupFastThreadLocals;
private InternalThreadLocalMap threadLocalMap;
public final InternalThreadLocalMap threadLocalMap() { return threadLocalMap; }
public final void setThreadLocalMap(InternalThreadLocalMap map) { this.threadLocalMap = map; }
}ftlt holds its own InternalThreadLocalMap, enabling fast access to ftl values.
2.4 FastThreadLocal Implementation
private final int index;
public FastThreadLocal() { index = InternalThreadLocalMap.nextVariableIndex(); }
public final V get() {
InternalThreadLocalMap map = InternalThreadLocalMap.get();
Object v = map.indexedVariable(index);
if (v != InternalThreadLocalMap.UNSET) return (V) v;
V value = initialize(map);
registerCleaner(map);
return value;
}The nextVariableIndex() method atomically increments a global counter, guaranteeing unique indices.
2.5 Degradation on Ordinary Threads
If a thread is not an instance of FastThreadLocalThread, Netty falls back to a slow path that stores the InternalThreadLocalMap in a regular JDK ThreadLocal, causing performance to revert to the standard ThreadLocal behavior.
3 Resource Reclamation Mechanisms
Netty provides three ways to clean up ftl values:
Automatic : When a FastThreadLocalRunnable wrapped task finishes, the associated ftl is cleared.
Manual : Users can invoke remove() on ftl or its map.
Cleaner‑based : A Cleaner registers with the thread to release ftl when the thread becomes unreachable (commented out in Netty 4.1.34).
4 FastThreadLocal Usage in Netty
The primary use case is allocating ByteBuf objects. Each thread owns a PoolArena; when a buffer is needed, the thread first tries its own arena, falling back to a global pool if necessary. This reduces contention and improves throughput.
final class PoolThreadLocalCache extends FastThreadLocal<PoolThreadCache> {
@Override
protected synchronized PoolThreadCache initialValue() {
Thread current = Thread.currentThread();
if (useCacheForAllThreads || current instanceof FastThreadLocalThread) {
return new PoolThreadCache(heapArena, directArena, tinyCacheSize, smallCacheSize, normalCacheSize,
DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL);
}
return new PoolThreadCache(heapArena, directArena, 0, 0, 0, 0, 0);
}
}Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
