- 缺点是索引计算时间复杂度高 , 请根据自己场景衡量 。
9)如果要读一个int , 用Bytebuf.readInt() , 不要Bytebuf.readBytes(buf , 0 , 4)
- 这能避免一次memory copy (long , short等同理) 。
10)配置
UnpooledUnsafeNoCleanerDirectByteBuf来代替jdk的DirectByteBuf , 让netty框架基于引用计数来释放堆外内存
io.netty.maxDirectMemory:
- < 0: 不使用cleaner , netty方面直接继承jdk设置的最大direct memory size , (jdk的direct memory size是独立的 , 这将导致总的direct memory size将是jdk配置的2倍) 。
- == 0: 使用cleaner , netty方面不设置最大direct memory size 。
0:不使用cleaner , 并且这个参数将直接限制netty的最大direct memory size , (jdk的direct memory size是独立的 , 不受此参数限制) 。
11)最佳连接数
- 一条连接有瓶颈 , 无法有效利用cpu , 连接太多也白扯 , 最佳实践是根据自己场景测试 。
12)使用PooledBytebuf时要善于利用
-Dio.netty.leakDetection.level 参数
- 四种级别:DISABLED(禁用) , SIMPLE(简单) , ADVANCED(高级) , PARANOID(偏执) 。
- SIMPLE , ADVANCED采样率相同 , 不到1%(按位与操作 mask ==128 - 1) 。
- 默认是SIMPLE级别 , 开销不大 。
- 出现泄漏时日志会出现“LEAK: ”字样 , 请时不时grep下日志 , 一旦出现“LEAK: ”立刻改为ADVANCED级别再跑 , 可以报告泄漏对象在哪被访问的 。
- PARANOID:测试的时候建议使用这个级别 , 100%采样 。
13)Channel.attr() , 将自己的对象attach到channel上
- 拉链法实现的线程安全的hash表 , 也是分段锁(只锁链表头) , 只有hash冲突的情况下才有锁竞争(类似ConcurrentHashMapV8版本) 。
- 默认hash表只有4个桶 , 使用不要太任性 。
9 从 Netty 源码中学到的代码技巧
1)海量对象场景中
AtomicIntegerFieldUpdater --> AtomicInteger
- Java中对象头12 bytes(开启压缩指针的情况下) , 又因为Java对象按照8字节对齐 , 所以对象最小16 bytes , AtomicInteger大小为16 bytes , AtomicLong大小为 24 bytes 。
- AtomicIntegerFieldUpdater作为static field去操作volatile int 。
2)FastThreadLocal , 相比jdk的实现更快
- 线性探测的Hash表 —> index原子自增的裸数组存储 。
3)IntObjectHashMap / LongObjectHashMap …
- Integer—> int
- Node[] —> 裸数组
4)RecyclableArrayList
- 基于前面说的Recycler , 频繁new ArrayList的场景可考虑 。
5)JCTools
- 一些jdk没有的 SPSC/MPSC/SPMC/MPMC 无锁并发队以及NonblockingHashMap(可以对比ConcurrentHashMapV6/V8)
推荐阅读
- 床上有蚂蚁如何彻底清除 床上有小蚂蚁怎么清除
- Oracle如何创建只读用户
- API攻击原理,以及如何识别和预防
- 如何辨别网购衣服的质量
- 普洱茶烟50块钱的,什么是普洱茶普洱茶的简介
- 华熙生物|500斤胖猴仔偷吃泡面被抓,满脸委屈如同小媳妇,网友:活该胖死
- 小花飞燕草和大花飞燕草,飞燕草花期和花语
- 翡翠|夏天佩戴翡翠,如果不想影响美观,注意以下这三点!
- 如何解决宏碁台式电脑没有声音
- 晚上吃茴香如同吃砒霜,晚上吃姜等于吃砒霜吗
