golang下极致性能socket开发

4 篇文章 0 订阅
2 篇文章 0 订阅

优化记录

1. SendMessage时,一定是调用方将message转换为[]byte数据序列,避免在其他线程转换时引发并发问题
2. socket写数据优化。socket写数据核心流程:message序列化->写入socket,有些socket库,存在重复拷贝的问题,基于核心流程,减少不必要的拷贝和内存分配,进行如下优化:
  1. 每个连接定义一个write_buffer,用来减少tcp报文数量:假如同时发送多个消 息时,不需要每个消息都要立即写入socket,只需每个消息调用session的WriteMessage接口暂时写入到write_buffer,最后调用Flush时统一写入到socket
  2. 减少message序列化时内存分配,session中定义cacheBufferList chan []byte缓存数据列表,每次序列化时从其中拿一个buffer,写入到socket后返还回去,如果取不到再使用`make([]byte, xxx_size)直接分配buffer。估测90%以上的消息都能通过该流程简化(比直接从内存中make快,并且减少内存碎片)
  3. `减少内存重复拷贝:如果是直接Send数据,那么无需拷贝到writebuffer,可直接写入到socket
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分配
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值