@garretwu thanks for reporting... I will check and fix it
 @garretwu I'm right you say it should get the 7th cache bin(start from0) . right ?
 you are right, @normanmaurer. That is what I mean.
 Thanks for clarify!

> Am 12.11.2014 um 03:52 schrieb garretwu notifications@github.com:
> 
> you are right, @normanmaurer. That is what I mean.
> 
> —
> Reply to this email directly or view it on GitHub.
 Totally forgot about this. Will look into it or would you want to submit a pr @garretwu ? We love contributions :)
 @garretwu what you think about provide a PR for this ? I'm still not 100 % sure I understand the issue correctly, so maybe it would be the easiest to just have you fix it ;)
 sure, I could create a PR:)
 This would be awesome!

> Am 11.04.2015 um 00:02 schrieb garretwu notifications@github.com:
> 
> sure, I could create a PR:)
> 
> —
> Reply to this email directly or view it on GitHub.
 Hi @normanmaurer. 
PR: https://github.com/netty/netty/pull/3624 is created for such issue.

mvn test pass.

end to end test:
Dumped heap to check.
with Dio.netty.allocator.maxCachedBufferCapacity: 32768 (cache max 32K),
NormalMemoryRegionCache size is 3(8k, 16k, 32k), rather than previous 4.
 Fixed by #3624

NormalMemoryRegionCache's arraysize is over booked
When create NormalMemoryRegionCache for PoolThreadCache. The array size is decided by:
        int max = Math.min(area.chunkSize, maxCachedBufferCapacity);
        int arraySize = Math.max(1, max / area.pageSize);

So most likely it is decided by maxCachedBufferCapacity/area.pageSize, with maxCachedBufferCapacity=2M the array size will be 2^8 = 256.

when we try to get normal cache the index is pre-processed by log2():
PoolThreadCache.cacheForNormal():
        int idx = log2(normCapacity >> numShiftsNormalHeap);
        return cache(normalHeapCaches, idx);

A 2M cache entry will get from the 8th cache bin(start from 0).

The space for NormalMemoryRegionCache is over booked, though it will not impact correctness(just a little performance..).

buffer/src/main/java/io/netty/buffer/PoolThreadCache.java
buffer/src/main/java/io/netty/buffer/PoolThreadCache.java
diff --git a/buffer/src/main/java/io/netty/buffer/PoolThreadCache.java b/buffer/src/main/java/io/netty/buffer/PoolThreadCache.java
index 755f1573ed7..fbcfaafffb1 100644
--- a/buffer/src/main/java/io/netty/buffer/PoolThreadCache.java
+++ b/buffer/src/main/java/io/netty/buffer/PoolThreadCache.java
@@ -129,7 +129,7 @@ private static <T> NormalMemoryRegionCache<T>[] createNormalCaches(
             int cacheSize, int maxCachedBufferCapacity, PoolArena<T> area) {
         if (cacheSize > 0) {
             int max = Math.min(area.chunkSize, maxCachedBufferCapacity);
-            int arraySize = Math.max(1, max / area.pageSize);
+            int arraySize = Math.max(1, log2(max / area.pageSize) + 1);
 
             @SuppressWarnings("unchecked")
             NormalMemoryRegionCache<T>[] cache = new NormalMemoryRegionCache[arraySize];
