优化记录
1. SendMessage时,一定是调用方将message转换为[]byte数据序列,避免在其他线程转换时引发并发问题
2. socket写数据优化。socket写数据核心流程:message序列化->写入socket,有些socket库,存在重复拷贝的问题,基于核心流程,减少不必要的拷贝和内存分配,进行如下优化:
cacheBufferList chan []byte
4. socket读数据优化。socket读数据核心流程:socket读数据到buffer->根据buffer序列化message
每个连接定义一个read_buffer和read_decode_buffer:socket读入到read_buffer,然后直接根据read_buffer中的数据解析出message,循环复用read_buffer,并且减少拷贝
5. 分包策略
目前大部分解包/封包都会写入消息的长度,一般都是用int(4个字节)表示,采用SOCKET封包和解包动态策略可以给绝大部分消息节省2/3个字节
6. 减少read和write协程中select的chan数量
由于select操作每增加一个chan的查询,会带来一定得查询消耗,为了提高read和write效率,因此建议这俩协程select的chan数量严格控制(看到有些socket库在select加上quitChan,可以去除,提高性能)
7. EncodeMessage时使用sync.Pool分配writeBuffer,减少GC压力
将pool按照buffer大小分段:32、64、128、256、512、1024
当bufferSize越小make([]byte, 0, size)越快
当bufferSize越大sync.Pool越快
如下是测试10000000次分配buffer时,不同bufferSize下的耗时对比
其中TestMakeBytes是采用make([]byte, 0, bufferSize)分配
TestMakeBufferBySyncPool是采用sync.Pool分配