随着JVM虚拟机和JIT即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓冲区Buffer,情况却稍有不同,特别是对于堆外直接内存的分配和回收,是一件耗时的操作。为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制。性能测试表明,采用内存池的ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右(性能数据与使用场景强相关)。
在4.x版本中,UnpooledByteBufAllocator是默认的allocator,尽管其存在某些限制。现在PooledByteBufAllocator已经广泛使用一段时间,并且我们有了增强的缓冲区泄漏追踪机制,所以是时候让PooledByteBufAllocator成为默认了。
优化前:
 
在玩家达到1100左右时直接内存迅速升高,CPU占用也飙高,
 
在最高峰时,服务器堆内存总共 3993 M,占用堆内存 3476 M,直接内存总共 2048 M,占用直接内存 715.8125 M。
 
 

 
发现netty底层的对象占用了很多
 
 

 
 
Class Name  | Shallow Heap  | Retained Heap  | 
  |  8  |  166,381,728  | 
  |  64  |  61,389,640  | 
  |  40  |  56,363,384  | 
  |  64  |  48,234,856  | 
  |  24  |  45,883,384  | 
  |  40  |  45,730,344  | 
  |  40  |  43,118,248  | 
  |  40  |  41,260,728  | 
  |  40  |  33,083,800  | 
  |  40  |  32,922,432  | 
  |  72  |  25,823,800  | 
  |     |     | 
    
 
优化,猜测是因为直接内存不够用,在反复申请空间,导致CPU占用,并且直接内存一直回收不掉!使用对象池后,1380人,CPU占用大概为100/1200,表现很稳定,FULLGC 次数为0
 
服务器堆内存总共 3993 M,占用堆内存 2150 M,直接内存总共 2048 M,占用直接内存 400.00098 M
 
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
 
   0.00   0.71   8.87  15.05  71.87    175    2.638     0    0.000    2.638 
 
 
主要是加了以下两句:
 
 bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
 
 bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);/ / 关键是这句
 
 
 
 
Class Name  | Shallow Heap  | Retained Heap  | 
  |  8  |  126,628,072  | 
  |  64  |  61,391,800  | 
  |  64  |  48,234,856  | 
  |  40  |  8,975,440  | 
  |  80  |  8,652,528  | 
  |  32  |  7,340,056  | 
  |  56  |  5,910,288  | 
  |  40  |  5,231,256  | 
  |  200  |  5,172,192  | 
  |  40  |  4,572,560  | 
Total: 10 entries  |     |     | 
 
 
总结:这次优化,内存省下1.7G,直接内存剩下300M,并且表现稳定,在线人数提升了300人(可能受带宽的限制,否则表现应该会更好),CPU从占用100%降到10%。










