免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8398 | 回复: 11
打印 上一主题 下一主题

[C++] 单线程CPU占用17%,50个线程CPU占用20%,性能下降,什么原因? [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-01-10 13:36 |只看该作者 |倒序浏览
当我将程序只开启一个线程时,做压力测试,CPU占用17%左右,当我吧线程数调整成50个线程时,发现CPU竟然达到了20%,性能不提升,反而下降,相同的测试用户数.

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
2 [报告]
发表于 2015-01-10 21:31 |只看该作者
线程间同步太多了,不信你开500个会更慢

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2015-01-11 15:23 |只看该作者
多线程并不会减少程序的计算量,多线程只是减少了等待时间。 如果单线程的时候等待花的时间不多,那换成多线程不但没有减少占用CPU,反而因为增加了上下文切换而占用了更多的CPU。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
4 [报告]
发表于 2015-01-11 19:25 |只看该作者
jd808 发表于 2015-01-10 13:36
当我将程序只开启一个线程时,做压力测试,CPU占用17%左右,当我吧线程数调整成50个线程时,发现CPU竟然达到了2 ...

要弄清楚是哪种类型的负载,才能评价采取什么方法来改进。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2015-01-12 10:55 |只看该作者
csumck 发表于 2015-01-11 15:23
多线程并不会减少程序的计算量,多线程只是减少了等待时间。 如果单线程的时候等待花的时间不多,那换成多 ...

估计你是对的,我是这个架构的,一个线程做socket的读写操作,另外一个线程池作为具体工作处理,不过具体工作本身就不大,就是吧数据转发出去而已.线程池通过互斥锁,争取资源(获得管道使用权,这个锁是主线程和线程池之间的),获取到管道后,读取消息,然后在加个锁(解决同一个fd只能一个线程在处理),处理完成后,就转发给另外一个服务程序处理.这个程序的任务就算完成啦.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2015-01-12 10:57 |只看该作者
yulihua49 发表于 2015-01-11 19:25
要弄清楚是哪种类型的负载,才能评价采取什么方法来改进。
具体的负载情况好像只能猜测,具体情况不太清楚.目前猜测有可能是锁引起的线程切换引起的.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2015-01-12 10:58 |只看该作者
windoze 发表于 2015-01-10 21:31
线程间同步太多了,不信你开500个会更慢
试了下,确实慢了,就2两把锁而已,不会太多的,上面一层已经描述了,锁的作用,去掉的话,那程序准奔溃.

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
8 [报告]
发表于 2015-01-12 11:42 |只看该作者
回复 7# jd808

关键不是有多少个锁,而是这些锁争用的次数,如果你只有一把锁锁住所有资源然后让一堆线程抢,那实际上会比单线程还慢,因为每个线程根本无法并行运行。
想要减少锁的争用,就必须尽量让每把锁管理的资源只由少数线程使用,对于你的情况,最简单的方案,你可以把socket和task按照一定的规则分成几个partition,然后给每个partition一个线程池,这样partition之间的争用就基本消除了,多个partition可以完全并行运行,每个partition内的争用当然还是没变,但由于socket和task都减少了,争用情况也会有一定缓解。

当然还有更高效但也更复杂的方案,但都要根据具体情况分析,先不废话了。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2015-01-12 16:58 |只看该作者
windoze 发表于 2015-01-12 11:42
回复 7# jd808

关键不是有多少个锁,而是这些锁争用的次数,如果你只有一把锁锁住所有资源然后让一堆线 ...
谢谢,我先把管道锁变成为每个线程订制一把,这样,线程池就不会抢啦,只会等待任务的到来,改好试试看.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2015-01-12 18:06 |只看该作者
windoze 发表于 2015-01-12 11:42
回复 7# jd808

关键不是有多少个锁,而是这些锁争用的次数,如果你只有一把锁锁住所有资源然后让一堆线 ...

我吧线程的管道锁去掉了,没任何效果,现在只有用户socket锁,这个锁的粒度很细,锁到每个用户身上了,还有一把链表锁,这个链表存储者所有的用户句柄,对这个链表遍历的时候必须加锁,否则万一其他线程删除掉了fd就没则了,只能报段错误咯,(遍历链表,将消息发送给指定的几个用户,通过id进行一一对比),链表也没想到办法将他分成几个链表,实际上现在就是用了200个链表,每个连表里存200个用户,这些用户又没法用区域隔开.
  1. int i;
  2.                 ConnList* plist;
  3.                 ConnList* m_UserList = g_pServer->GetUserList();
  4.                 for (i=0; i<g_pServer->GetNodeListCount(); i++) {
  5.                         plist = &m_UserList[i];
  6.                         pthread_rwlock_rdlock(&plist->ConnListLock);
  7.                         while (pcon != NULL) {
  8.                                 if(pcon->fd_type == 1){
  9.                                         if(m_conn->operators_id==pcon->operators_id&&m_conn->server_id==pcon->server_id)
  10.                                                 to_client(pcon,m_sbuff,command,g_pConf->STRZIP);
  11.                                 }
  12.                                 pcon = pcon->GetNext();
  13.                         }
  14.                         pthread_rwlock_unlock(&plist->ConnListLock);
  15.                 }
复制代码
但这个也就是个读写锁,应该没太大关系吧.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP