双11狂欢大促

盲盒赢 定制羽绒服

开启惊喜盲盒,抽取你的专属好礼

— 惊喜奖品抢先看 —

从4秒钟发送5GB数据所引发的对IOCP重叠操作的思索

Squall_zy Squall_zy 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
  先澄清一下,标题只是个噱头,所谓发送5GB数据实为重叠投递5GB的发送数据,并非真的发送了5GB数据。写这个帖子只是因为最近看了很多IOCP的文章,我觉得大部分的文章都会误导读者对IOCP的使用。这里我只想表述下我对IOCP的理解。同时希望抛砖引玉,得到更多的信息。
  4秒投递5GB,的确是可以做到的。这意味着你瞬间就安排了发送工作,而眼看着对面的机器花几十分钟的时间来完成对数据的接收。(注意,这几十分钟时间内,发送端应用层并没有做任何send动作)。
  在这种情况下,IOCP的发送可以达到最高的效率,唯有这种方式才是发挥了Overlapped的优势。在这种情况下,发送操作是使用用户Buf直接发的,而不需要通过socket的发送缓冲区。(这是性能的关键)

在这里,我想举个反例,这是我看到的文章中犯的最多的一个错误。看下面的结构体:
typedef struct _PER_IO_CONTEXT
{
OVERLAPPED m_Overlapped;
WSABUF m_wsaBuf;
char m_szBuffer[MAX_BUFFER_LEN]; (这里就是问题!!)
OPERATION_TYPE m_OpType;
} PER_IO_CONTEXT;

外部调用接口:
BOOL PostSend( ..., ..., LOVOID pBuf, UINT nSize );

我仅从内存拷贝方面说明上例为何效率不高。
1、还是结合实际应用吧,这样最能说明问题。通常发送TCP数据,要么是定长报文,要么是带头报文。我暂且不说在带头报文长度大于MAX_BUFFER_LEN时,这东西都不能用。假设要发送带头报文,用户首先要开辟一块内存,把报头和身体填充好(这是一次内存拷贝);在调用PostSend函数时,IOCP类会把用户内存拷贝至m_szBuffer变量中作为投递缓存实体(这是第二次内存拷贝);当协议栈处于非SEND_PENDING状态下,WSASend函数会将m_szBuffer的内容拷贝至发送缓冲区(这是第三次内存拷贝);让人惊讶的是,为了发送一个TCP报文,居然消耗了三次内存拷贝的资源和时间。这就是效率低下的根源。
2、还有,你要投递5GB的数据,如果使用如上的结构体,你根本连内存都开不出来。这是因为上面的结构体人为地为每一次发送准备一块内存。假设你要把一个相同的文件同时发给10000个客户端,用上面这个例子会立刻让你服务器瘫痪。
3、真正享受到Overlapped性能的程序,只会使用一次内存拷贝,而不是三次!这需要用户来提供一块发送Buf,并且对该Buf的生存周期负责任;另外,想办法让系统尽量工作于SEND_PENDING状态,免去到发送缓冲区的内存拷贝。
4、最后一个问题是发送缓冲区、接收缓冲区是否该置0的讨论。这个讲起来理论有点多,我只能说各有各的好处。我个人使用不会置0,但如果你对服务器总处于重叠投递状态非常有把握,置0丝毫不会影响性能。但如果你没有把握,那么置0会延后客户端的发送时机(虽然少一次内存拷贝,但滞后了响应时间,所以得不偿失)。
...全文
游戏服务器开发面试精解 这是一份游戏服务器开发方向的面试题库,共 295 题,覆盖游戏服务端架构、网络通信、同步模型、场景管理、战斗系统、数据存储、分服容灾、反作弊运维等核心链路,交付三种阅读版本,方便随时翻看。 内容主线按面试实际被追问的路径组织,覆盖十二个模块:游戏服务器整体架构与进程模型、网络通信(TCP/KCP/UDP/协议设计)、同步模型(状态同步、帧同步、预测回滚)、场景管理与 AOI、战斗与技能系统、任务活动与商业化系统、数据库设计与数据落地、缓存与内存数据库(Redis)、分区分服跨服与合服、高并发容灾与回档、防作弊与外挂对抗、运维监控日志与线上事故处理。 游戏服务端和普通后端不同,考的不是 Redis 分布式锁这种背一遍就行的八股,而是 100 人同屏广播怎么压、帧同步不同步怎么查、回档事故怎么收场这类一线踩坑题。作者面过腾讯 IEG、网易雷火、米哈游等公司的服务端岗,按公开面经频次统计后重新出题并逐题写解答。每题先给一句能直接说出口的结论,再展开原理或排查步骤,最后列回答要点;带追问标记的题顺着项目场景往下挖。版本基准对齐 C++17、Linux epoll、MySQL 8.0 InnoDB、Redis 7.2、MongoDB 6.0、protobuf、KCP,Netty 与 Go 在对比题里提到。 适合准备校招或一到三年社招、目标腾讯、网易、米哈游、莉莉丝、三七等游戏服务端岗的同学,C++ 为主的服务器方向最对口,Go 或 Netty 栈的同学看网络和架构部分也通用。 使用时第一遍从头过,盖住答案自己说一遍,卡壳的标星;第二遍只看标星和高频题;面试前重点看同步、战斗、回档三个模块,追问别跳过。 立即下载

相关推荐

评论 26
收藏 已收藏
分享
返回顶部
Squall_zy
网络编程 18,356 成员 64,161 内容