密集数据发送中断 IOCP 事件
intensive data sending breaks IOCP events
我在我的应用程序中使用 Windows IOCP
几年没有任何问题(与小消息的永久 TCP
通信),但最近我不得不发送非常大的应用程序状态(25k 条消息,大约总共 12Mb)。
我使用 0x2000 字节的缓冲区,结合 IOCP
事件:第一个 write
触发器 WSASend
,所有其他的只是填充缓冲区。当 GetQueuedCompletionStatus
收到事件时,写入完成,下一个缓冲区通过 WSASend
发送,依此类推。
这是我第一次使用这样的用例一次发送这么大的数据。我注意到,一段时间后 GetQueuedCompletionStatus
停止接收事件。
这是可视化的,缓冲区中的数据是如何从 IOCP 回调发送的:
14:16:19.894, WSASend scheduled buffer size (3005) , pendingWrite bytes 3005
14:16:20.021, WSASend scheduled buffer size (1175) , pendingWrite bytes 1175
14:16:20.276, WSASend scheduled buffer size (4652) , pendingWrite bytes 4652
14:16:20.411, WSASend scheduled buffer size (2135) , pendingWrite bytes 2135
14:16:20.604, WSASend scheduled buffer size (3366) , pendingWrite bytes 3366
14:16:20.835, WSASend scheduled buffer size (3718) , pendingWrite bytes 3718
14:16:20.943, WSASend scheduled buffer size (665) , pendingWrite bytes 665
14:16:21.087, WSASend scheduled buffer size (2931) , pendingWrite bytes 2931
14:16:21.109, WSASend scheduled buffer size (296) , pendingWrite bytes 296
14:16:21.109, WSASend scheduled buffer size (21) , pendingWrite bytes 21
14:16:21.182, WSASend scheduled buffer size (380) , pendingWrite bytes 380
14:16:21.184, WSASend scheduled buffer size (160) , pendingWrite bytes 160
14:16:21.355, WSASend scheduled buffer size (5885) , pendingWrite bytes 5885
14:16:21.531, WSASend scheduled buffer size (8169) , pendingWrite bytes 16135 <-- here buffers start growing
14:16:21.691, WSASend scheduled buffer size (8173) , pendingWrite bytes 19727
14:16:21.692, WSASend scheduled buffer size (8176) , pendingWrite bytes 11554
如您所见,过了一会儿,pendingWrite 开始增长,但没关系,我有很多内存来缓冲它。但是在最后一次发送之后(在 14:16:21.692
)GetQueuedCompletionStatus
根本不会触发。
我尝试将 send/receive 套接字缓冲区 (SO_RCVBUF/SO_SNDBUF) 增加到 80Kb,但看起来没有任何效果。
我不知道,接下来我应该检查什么,WSASend
没有 return 任何错误(只有 ERROR_IO_PENDING
是预期的)。
PS:通信在同一台PC上,Windows 7 x64。
简而言之:我的假设是,代码运行良好l,所以我猜想,IOCP
(或套接字)设置不适合这样的吞吐量,或者也许套接字缓冲区有一些限制。
回答:代码有竞争条件,所以有时 receiver
停止从套接字中消耗数据,这就是为什么 sending
套接字的缓冲区最终达到了它的限制,并且GetQueuedCompletionStatus
套接字的写回调没有触发新事件。
总结:IOCP
按预期工作,不需要额外的配置。
当 race 固定后,我可以在瞬间发送超过 150k 的小数据包(20-200 字节)。
我在我的应用程序中使用 Windows IOCP
几年没有任何问题(与小消息的永久 TCP
通信),但最近我不得不发送非常大的应用程序状态(25k 条消息,大约总共 12Mb)。
我使用 0x2000 字节的缓冲区,结合 IOCP
事件:第一个 write
触发器 WSASend
,所有其他的只是填充缓冲区。当 GetQueuedCompletionStatus
收到事件时,写入完成,下一个缓冲区通过 WSASend
发送,依此类推。
这是我第一次使用这样的用例一次发送这么大的数据。我注意到,一段时间后 GetQueuedCompletionStatus
停止接收事件。
这是可视化的,缓冲区中的数据是如何从 IOCP 回调发送的:
14:16:19.894, WSASend scheduled buffer size (3005) , pendingWrite bytes 3005
14:16:20.021, WSASend scheduled buffer size (1175) , pendingWrite bytes 1175
14:16:20.276, WSASend scheduled buffer size (4652) , pendingWrite bytes 4652
14:16:20.411, WSASend scheduled buffer size (2135) , pendingWrite bytes 2135
14:16:20.604, WSASend scheduled buffer size (3366) , pendingWrite bytes 3366
14:16:20.835, WSASend scheduled buffer size (3718) , pendingWrite bytes 3718
14:16:20.943, WSASend scheduled buffer size (665) , pendingWrite bytes 665
14:16:21.087, WSASend scheduled buffer size (2931) , pendingWrite bytes 2931
14:16:21.109, WSASend scheduled buffer size (296) , pendingWrite bytes 296
14:16:21.109, WSASend scheduled buffer size (21) , pendingWrite bytes 21
14:16:21.182, WSASend scheduled buffer size (380) , pendingWrite bytes 380
14:16:21.184, WSASend scheduled buffer size (160) , pendingWrite bytes 160
14:16:21.355, WSASend scheduled buffer size (5885) , pendingWrite bytes 5885
14:16:21.531, WSASend scheduled buffer size (8169) , pendingWrite bytes 16135 <-- here buffers start growing
14:16:21.691, WSASend scheduled buffer size (8173) , pendingWrite bytes 19727
14:16:21.692, WSASend scheduled buffer size (8176) , pendingWrite bytes 11554
如您所见,过了一会儿,pendingWrite 开始增长,但没关系,我有很多内存来缓冲它。但是在最后一次发送之后(在 14:16:21.692
)GetQueuedCompletionStatus
根本不会触发。
我尝试将 send/receive 套接字缓冲区 (SO_RCVBUF/SO_SNDBUF) 增加到 80Kb,但看起来没有任何效果。
我不知道,接下来我应该检查什么,WSASend
没有 return 任何错误(只有 ERROR_IO_PENDING
是预期的)。
PS:通信在同一台PC上,Windows 7 x64。
简而言之:我的假设是,代码运行良好l,所以我猜想,IOCP
(或套接字)设置不适合这样的吞吐量,或者也许套接字缓冲区有一些限制。
回答:代码有竞争条件,所以有时 receiver
停止从套接字中消耗数据,这就是为什么 sending
套接字的缓冲区最终达到了它的限制,并且GetQueuedCompletionStatus
套接字的写回调没有触发新事件。
总结:IOCP
按预期工作,不需要额外的配置。
当 race 固定后,我可以在瞬间发送超过 150k 的小数据包(20-200 字节)。