c++异网高效发送数据
原文
strand
,锁+发送
队列和提交+发送
队列,哪种方法更好呢?性能说话.答案是提交+发送队列>锁+发送队列>strand
.
提交
方法连续发送数据
的另一个好处是,内部io
线程需要连续发送数据
时是无锁的,只有提交
那里有锁,锁的范围很小,同时也影响io
线程发数据的效率
,它的效率无疑是最高的
.
另一个场景,需要发送一段数据
到服务端,数据包括包头和包体
,包头
中有表示包体
长度的长度
字段,服务端
先读包头
解析出包体长度
后再读包体
.客户端这样发送数据
的:
空 发送(串 负载){
向量<符>缓冲;
大小型 大小=负载.大小();
缓冲.调整(大小+4);
复制内存(缓冲.数据(),&大小,4);//包头
复制内存(缓冲.数据()+4,负载.数据(),大小);
//包体.
异步写(异网::缓冲(缓冲));//发送.
}
代码很简单,先构造完整长度的缓冲
,然后拷贝包头
,再拷贝包体
,最后发送
.这里有个问题
就是有一内存分配
(一次是负载
,一次是缓冲
)和两次内存拷贝
,性能较低
.如何优化性能呢?可用零拷贝
来发送数据.
0拷贝
代码变成:
空 发送(串 负载){
向量<异网::常缓冲>缓冲;
大小型 大小=负载.大小();符 头[4];
复制内存(头,&大小,4);
缓冲.压后(异网::缓冲(头,4));
缓冲.压后(异网::缓冲(负载.数据(),负载.大小()));
异步写(缓冲);
}
这里代码没有分配内存
,只有一次memcpy(head)
,效率比之前高很多,这里省掉了复制负载
,称为零拷贝
方式发送数据,或者称为分散-聚集
方式,asio
提供了发送std::vectorasio::常缓冲
的接口,使用
它可实现零拷贝
方式发送数据
.
零拷贝
底层用writev
来一次发送多个缓冲
.
虽然零拷贝
避免了额外分配和拷贝
内存,但是一次发送多个缓冲
的效率并没有一次发送大缓冲
效率高,所以要看具体
情况,如果是小数据
,分配和拷贝
内存代价较小反而比零拷贝
方式更高效.
再改进
避免多次分配
内存和发送多个
缓冲:
空 发送(串 负载){
向量<异网::常缓冲>缓冲;
大小型 偏移=4,大小=负载.大小()-偏移;
复制内存(负载.数据(),&大小,4);
异步写(异网::缓冲(负载.数据(),负载.大小()));
}
这里在构造负载
时候预留出包头
部分长度,保证后面发送
时不会再复制负载
,只复制
包头很少的数据,同时一次发送负载
,效率更高.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现