求教IOCP并发处理

帝国队长 2014-09-12 01:38:34
最近学习了一下IOCP 的东西。 模仿的是http://blog.csdn.net/piggyxp/article/details/6922277 By PiggyXP(小猪) 上的代码来实现的。

然后加入了自己的内容(相当于移动AOI),一个移动坐标广播,100个人 每一秒移动一次,每每动一次就要向其它100人广播(其实是99)。 算起来,1秒就要触发 1W个投递

现在问题是
1 处理并发很慢啊。 1W个但处理10多秒才能处理完成。 造成了拥堵。各位是怎么处理这种批量操作的。感觉步骤很简单,没有什么特别耗费效率的功能啊。但就是速度上不去。
2 我模拟的By PiggyXP(小猪) 的代码。好像有内存泄露。 看了一下他的代码运行。好像也有一样的现象。但就没看出来是哪里出的问题。希望哪位大哥指点一下。
...全文
179 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
估计就是因为本机处理所以才慢,因为IO不需要延时,你刚发它马上完成,cpu都用于处理IO了,没时间切换线程去触发完成端口事件了。
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
这个我知道的。 我其实主要是想测试一下才这样做的,因为之前学习IOCP之前听各位大神说得相当牛B,所以故意做了这样一个不合理的场景测试, 预计应该没有问题。但事实上完全响应不过来。特别是接收,特别的慢 量有6000条,数据发送完了, 都要过个好几秒才能全部接收完成。 就是本机处理的。不存在延时问题 纠结啊。
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
那就是你的实现方案有问题了,对于每个人的每次移动,有必要那么实时通知另外99人吗?,为什么不能服务器记录所有人的坐标,收到客户端移动包先更新本地坐标,然后定时(比如半秒一次)发送所有人当前坐标给100人?这样你需要发送的包将数量级减少,从每秒1w个减少到每秒200个(假设半秒发一次)。
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
投递是肯定投递了的。因为发送并不止一次。后续还会有,只是相当拥堵。 不再发送命令后。都还要10多秒才能把上次的包发送完。
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
根据你的业务逻辑来看,你有100个socket投递了至少100个WSARecv, 在工作线程中每成功一个WSARecv后的处理又要投递99个WSASend()和一个WSARecv(),所以工作线程中这个查找对应socket的步骤非常关键,需要尽可能优化。 不过看来问题并不在这里,这点消耗对完成端口来说不大。 你是不是在处理WSARecv完成事件后忘了继续投递下一个WSARecv()?
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
呃。这个查找并无太大损耗。因为考虑到是长连,也是测试,用的是hash_map 基本上的查找可以说是常数级的跳转。
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
引用 8 楼 devilkillzzz 的回复:
[quote=引用 7 楼 Idle_ 的回复:] 既然你关联了100个socket到一个completion port, 那么在完成处理中你怎么对应完成事件和socket以及socket相对应的你的内部数据的? 不会是循环100次查找的吧?尽管100次的循环不大,但是你每处理一个socket的一次完成通知都需要循环100次那就有点浪费了,哪怕你用std map来对应查找都会显得慢。最好用completion key, overlapped结构等能够和socket以及你的内部结构形成直接对应,这样只要强制类型转换或+/-内存偏移量就可以直接访问你的内部数据,效率提高将很明显 -- 一点优化意见。
不是的。肯定不会是查找。 IOCP 只负责接收和发送。其它线程在负责这个循环。而且也只是单纯的循环,没有查找选择一说。[/quote] 错了,IOCP不负责发送/接收,它只负责发送/接收完成后的通知,通知给调用GetQueuedCompletionStatus()的工作线程,由工作线程中的代码处理这个发送/接收完成后该进行的下一步。而GetQueuedCompletionStatus()返回的只有completion key, overlapped struct和这个完成的发送/接收所操作的字节数。那么你想进行下一步操作,当然需要知道到底是谁上次的发送/接收完成了(你有100个socket关联到一个完成端口),那么找到这个“谁”不就需要根据已知条件(completion key, 和 overlapped struct)进行查找吗?
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
引用 7 楼 Idle_ 的回复:
既然你关联了100个socket到一个completion port, 那么在完成处理中你怎么对应完成事件和socket以及socket相对应的你的内部数据的? 不会是循环100次查找的吧?尽管100次的循环不大,但是你每处理一个socket的一次完成通知都需要循环100次那就有点浪费了,哪怕你用std map来对应查找都会显得慢。最好用completion key, overlapped结构等能够和socket以及你的内部结构形成直接对应,这样只要强制类型转换或+/-内存偏移量就可以直接访问你的内部数据,效率提高将很明显 -- 一点优化意见。
不是的。肯定不会是查找。 IOCP 只负责接收和发送。其它线程在负责这个循环。而且也只是单纯的循环,没有查找选择一说。
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
既然你关联了100个socket到一个completion port, 那么在完成处理中你怎么对应完成事件和socket以及socket相对应的你的内部数据的? 不会是循环100次查找的吧?尽管100次的循环不大,但是你每处理一个socket的一次完成通知都需要循环100次那就有点浪费了,哪怕你用std map来对应查找都会显得慢。最好用completion key, overlapped结构等能够和socket以及你的内部结构形成直接对应,这样只要强制类型转换或+/-内存偏移量就可以直接访问你的内部数据,效率提高将很明显 -- 一点优化意见。
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
引用 3 楼 Idle_ 的回复:
一点注意事项: completion port是为了配合overlapped IO提高效率搞出来的,因此你的发送/接收必须使用WSARecv/WSASend+overlapped方式进行才能在工作线程中进行处理。
是的。发处和接收都是用的wsarecv 和 wsasend
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
其实我主要不是太关心泄露。主要是更关心的是 并发处理量的问题 代码的话在这里下。 这是他的代码 http://download.csdn.net/detail/piggyxp/3739575 http://download.csdn.net/detail/piggyxp/3748595
赵4老师 2014-09-12
  • 打赏
  • 举报
回复
检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
一点注意事项: completion port是为了配合overlapped IO提高效率搞出来的,因此你的发送/接收必须使用WSARecv/WSASend+overlapped方式进行才能在工作线程中进行处理。
阿呆_ 2014-09-12
  • 打赏
  • 举报
回复
没有代码没有答案。 哪怕你给那个“小猪”发这样的问题他也不知道答案。
帝国队长 2014-09-12
  • 打赏
  • 举报
回复
没有人知道吗

18,356

社区成员

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

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