IOCP 性能问题,真的会越用越慢?

jasonabc1 2016-06-10 12:08:15
测试硬件:
64位 10 windows, 32 位程序(C/S)
I7 8 核
8G 内存

测试场景:

C 也是同 S 一样的 IOCP 核心, 共同占用了系统IO队列, 当然, 是两个独立的程序。 只是我想即然都使用 IOCP 核心, 应该都占用系统 的IOCP 队列

测试业务:
C 对 S 建立 TCP/IP 长连接, 连接后, 每 10 秒发送一次心跳 , 连接不主动断线

这是一个压力测试, 看看最大性能能达到何处:

先说说服务器状态:
S 基本不怎么耗 CPU 和 内存, 低耗一直在 10% 以下, 内存慢慢上升到 100M 左右
根据我的性能统计: S 每秒处理 1500次 IO 业务, 1000~2500的波动

问题:
从开始, 一直到完全没办法响应(大约 9000 个链接就超时的不要不要的了)

[23:06:01(580)]连接 Socket 建立成功,线程ID:735c,SOCKET = 1276
[23:06:01(580)]连接 Socket 建立成功,线程ID:2ec8,SOCKET = 1256
[23:06:01(593)]连接服务器成功 192.168.0.101:39999,线程ID:735c , 本地连接信息:192.168.0.101:32896,SOCKET = 1276,耗时:0.65ms
[23:06:01(594)]连接服务器成功 192.168.0.101:39999,线程ID:2ec8 , 本地连接信息:192.168.0.101:32897,SOCKET = 1256,耗时:0.45ms

直到后来, 现在 8000 个连接

[23:56:41(146)]连接服务器成功 192.168.0.101:39999,线程ID:2d7c , 本地连接信息:192.168.0.101:43193,SOCKET = 33380,耗时:16776.38ms
[23:56:41(146)]收接到 [ CHECKIN ] 耗时 22814.94ms
[23:56:41(147)]收接到 [ CHECKIN ] 耗时 22848.86ms

真是天差地别。。。 IOCP 是越用越慢的吗?
因为现在大级别耗时, 服务器和客户端的 CPU 都没超过 5% , 倒是系统自占用一直都是 20%

我理解, 有投递, 然后投递被处理, 然后队列会减少, 我不清楚怎样去监视或取得 IOCP 的系统所在的队列, 无法查看,就只能靠猜啊。
在 ProcXP 中, 看到 IO 处理的值如下(8000 个连接时)

S IO READS: 111
S IO WRITE 104,290
S IO OTHRE 1,857,981

C IO READS: 15
C IO WRITE 7,531,489
CIO OTHRE 1,933,050

我的理解是 READS 是 Recv, 为什么服务器才 111? 而 Write 却这么大, 还有那个 OTHER 是什么鬼, 更加大

不知道是否有解决过种问题的大神, 希望赐教一下。
...全文
1070 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
jasonabc1 2016-06-10
  • 打赏
  • 举报
回复
基本追踪得到, 不是我响应慢, 是 IOCP 响应慢。 而程序对回发处理只需要低于 5ms 的响应时间。 但是完成端口堆积过多导致。 有没有做过 IOCP 并发处理性能测试的? 我的机器配置, 差不多并客户端, 服务端占用系统并发处理为 5000次每秒(含少量业务)
jasonabc1 2016-06-10
  • 打赏
  • 举报
回复
好吧, 自己写贴子也是重新的审视, 我知道为什么 S & C 的 IO WRITE 为什么这么高了, 因为是在玩命的写日志, 不过依然不知道 OTHER 是什么, 有没有什么办法可以看 IOCP 队列的, 我想知道为什么IOCP为什么越来越慢
worldy 2016-06-10
  • 打赏
  • 举报
回复
引用 楼主 jasonabc1 的回复:
测试硬件: 64位 10 windows, 32 位程序(C/S) I7 8 核 8G 内存 测试场景: C 也是同 S 一样的 IOCP 核心, 共同占用了系统IO队列, 当然, 是两个独立的程序。 只是我想即然都使用 IOCP 核心, 应该都占用系统 的IOCP 队列 测试业务: C 对 S 建立 TCP/IP 长连接, 连接后, 每 10 秒发送一次心跳 , 连接不主动断线 这是一个压力测试, 看看最大性能能达到何处: 先说说服务器状态: S 基本不怎么耗 CPU 和 内存, 低耗一直在 10% 以下, 内存慢慢上升到 100M 左右 根据我的性能统计: S 每秒处理 1500次 IO 业务, 1000~2500的波动 问题: 从开始, 一直到完全没办法响应(大约 9000 个链接就超时的不要不要的了) [23:06:01(580)]连接 Socket 建立成功,线程ID:735c,SOCKET = 1276 [23:06:01(580)]连接 Socket 建立成功,线程ID:2ec8,SOCKET = 1256 [23:06:01(593)]连接服务器成功 192.168.0.101:39999,线程ID:735c , 本地连接信息:192.168.0.101:32896,SOCKET = 1276,耗时:0.65ms [23:06:01(594)]连接服务器成功 192.168.0.101:39999,线程ID:2ec8 , 本地连接信息:192.168.0.101:32897,SOCKET = 1256,耗时:0.45ms 直到后来, 现在 8000 个连接 [23:56:41(146)]连接服务器成功 192.168.0.101:39999,线程ID:2d7c , 本地连接信息:192.168.0.101:43193,SOCKET = 33380,耗时:16776.38ms [23:56:41(146)]收接到 [ CHECKIN ] 耗时 22814.94ms [23:56:41(147)]收接到 [ CHECKIN ] 耗时 22848.86ms 真是天差地别。。。 IOCP 是越用越慢的吗? 因为现在大级别耗时, 服务器和客户端的 CPU 都没超过 5% , 倒是系统自占用一直都是 20% 我理解, 有投递, 然后投递被处理, 然后队列会减少, 我不清楚怎样去监视或取得 IOCP 的系统所在的队列, 无法查看,就只能靠猜啊。 在 ProcXP 中, 看到 IO 处理的值如下(8000 个连接时) S IO READS: 111 S IO WRITE 104,290 S IO OTHRE 1,857,981 C IO READS: 15 C IO WRITE 7,531,489 CIO OTHRE 1,933,050 我的理解是 READS 是 Recv, 为什么服务器才 111? 而 Write 却这么大, 还有那个 OTHER 是什么鬼, 更加大 不知道是否有解决过种问题的大神, 希望赐教一下。
问题基本上是出在你的代码上,内存申请困难、文件没有分块处理、内存没有及时释放等等,都可能造成效率问题
jasonabc1 2016-06-10
  • 打赏
  • 举报
回复
引用 2 楼 worldy 的回复:
[quote=引用 楼主 jasonabc1 的回复:] 测试硬件: 64位 10 windows, 32 位程序(C/S) I7 8 核 8G 内存 测试场景: C 也是同 S 一样的 IOCP 核心, 共同占用了系统IO队列, 当然, 是两个独立的程序。 只是我想即然都使用 IOCP 核心, 应该都占用系统 的IOCP 队列 测试业务: C 对 S 建立 TCP/IP 长连接, 连接后, 每 10 秒发送一次心跳 , 连接不主动断线 这是一个压力测试, 看看最大性能能达到何处: 先说说服务器状态: S 基本不怎么耗 CPU 和 内存, 低耗一直在 10% 以下, 内存慢慢上升到 100M 左右 根据我的性能统计: S 每秒处理 1500次 IO 业务, 1000~2500的波动 问题: 从开始, 一直到完全没办法响应(大约 9000 个链接就超时的不要不要的了) [23:06:01(580)]连接 Socket 建立成功,线程ID:735c,SOCKET = 1276 [23:06:01(580)]连接 Socket 建立成功,线程ID:2ec8,SOCKET = 1256 [23:06:01(593)]连接服务器成功 192.168.0.101:39999,线程ID:735c , 本地连接信息:192.168.0.101:32896,SOCKET = 1276,耗时:0.65ms [23:06:01(594)]连接服务器成功 192.168.0.101:39999,线程ID:2ec8 , 本地连接信息:192.168.0.101:32897,SOCKET = 1256,耗时:0.45ms 直到后来, 现在 8000 个连接 [23:56:41(146)]连接服务器成功 192.168.0.101:39999,线程ID:2d7c , 本地连接信息:192.168.0.101:43193,SOCKET = 33380,耗时:16776.38ms [23:56:41(146)]收接到 [ CHECKIN ] 耗时 22814.94ms [23:56:41(147)]收接到 [ CHECKIN ] 耗时 22848.86ms 真是天差地别。。。 IOCP 是越用越慢的吗? 因为现在大级别耗时, 服务器和客户端的 CPU 都没超过 5% , 倒是系统自占用一直都是 20% 我理解, 有投递, 然后投递被处理, 然后队列会减少, 我不清楚怎样去监视或取得 IOCP 的系统所在的队列, 无法查看,就只能靠猜啊。 在 ProcXP 中, 看到 IO 处理的值如下(8000 个连接时) S IO READS: 111 S IO WRITE 104,290 S IO OTHRE 1,857,981 C IO READS: 15 C IO WRITE 7,531,489 CIO OTHRE 1,933,050 我的理解是 READS 是 Recv, 为什么服务器才 111? 而 Write 却这么大, 还有那个 OTHER 是什么鬼, 更加大 不知道是否有解决过种问题的大神, 希望赐教一下。
问题基本上是出在你的代码上,内存申请困难、文件没有分块处理、内存没有及时释放等等,都可能造成效率问题[/quote] 由于服务端程序并没有满负荷运行, 怎么就看出来我有 申请困难, 没有释放的问题呢? CPU 都没转动, 都处于等待中啊。
jasonabc1 2016-06-10
  • 打赏
  • 举报
回复
修正一下提问, 有没有什么 API 可以查询IOCP 队列信息的? 以便做出正确的处理。 连接数就不说了, 10W 静态连接轻轻松松, 但是, 若是带上业务处理, 那就麻烦了。 IOCP 说实在的, 有很蛋痛的点。 好的机器对不好的服务器, 分分钟干翻对方。。。
RRQMSocket是一个整合性的、超轻量级的网络通信服务框架。它具有高并发连接、高并发处理、事件订阅、插件式扩展、多线程处理、内存池、对象池等特点,让使用者能够更加简单的、快速的搭建网络框架。在发送效率上,同步发送可达20w/s,异步发送可达60w/s。服务器在接收、处理效率上因线程数量而定。 支持环境: .NETFramework4.5及以上。 .NETCore3.1及以上。 .NETStandard2.0及以上。 支持框架: WPF Winform Blazor Xamarin Mono Unity 其他(即所有C#系) 特点: 1、对象池 对象池在RRQMSocket有很多应用,最主要的两个就是连接对象池和处理对象池。连接对象池就是当客户端成功连接时,首先去连接对象池中找TcpSocketClient,然后没有的话,才创建。如果哪个客户端掉线了,它的TcpSocketClient就被回收。这也就是ID重用的原因。 然后就是处理对象池,在RRQMSocket中,接收数据的线程和IOCP内核线程是分开的,也就是比如说客户端给服务器发送了1w条数据,但是服务器收到后处理起来很慢,那传统的iocp肯定放慢接收速率,然后通知客户端的tcp窗口,发生拥塞,然后让客户端暂缓发送。但是在RRQMSocket中把收到的数据通过队列全都存起来,首先不影响iocp的接收,同时再分配线程去处理收到的报文信息,这样就相当于一个“泄洪湖泊”,能很大程度的提高处理数据的能力。 2、多线程 由于有处理对象池的存在,使多线程处理变得简单。在客户端连接完成时,自动分配该客户端辅助类(TcpSocketClient)的消息处理逻辑线程,假如服务器线程数量为10,则第一个连接的客户端被分配到0号线程中,第二个连接将被分配到1号线程中,以此类推,循环分配。当某个客户端收到数据时,将数据排入当前线程所独自拥有的队列当中,并唤醒线程执行。 3、传统IOCP和RRQMSocket RRQMSocket的IOCP和传统也不一样的,以微软官方为例,使用MemoryBuffer开辟一块内存,然后均分,然后给每个话分配一个区接收,等收到数据以后,再复制一份,然后把复制的数据抛出处理。而RRQMSocket是每次接收之前,从内存池拿一个可用内存块,然后直接用于接收,等收到数据以后,直接就把这个内存块抛出去了,这样就避免了复制操作,虽然只是细小的设计,但是在传输1000w次64kb的数据时,性能相差了10倍。所以也是基于此,文件传输时效率才高。 4、数据处理适配器 相信大家都使用过其他的Socket产品,例如HPSocket,SuperSocket等,那么RRQMSocket在设计时也是借鉴了其他产品的优秀设计理念,数据处理适配器就是其中之一,但和其他产品的设计不同的是,RRQMSocket的适配器功能更加强大,它可以无视真实的数据,而模拟出想要的数据,例如:可以对数据进行预处理,从而解决数据分包。粘包的问题,也可以直接解析HTTP协议,经过适配器处理后传回一个HttpRequest对象等。 5、粘包、分包解决 在RRQMSocket中处理TCP粘包、分包问题是非常简单的。只需要更改不同的数据处理适配器即可。例如:使用固定包头,只需要给TcpSocketClient和TcpClient赋值FixedHeaderDataHandlingAdapter的实例即可。同样对应的处理器也有固定长度、终止字符分割等。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧