免费注册 查看新帖 |

Chinaunix

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

[求教] 8核Linux上udp狂丢包问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-03-05 10:48 |只看该作者 |倒序浏览
udp server,可以简单理解为多线程echo程序。
如果线程为1,则可以接收300k pack/s, 基本没有丢包,
如果线程>1,则有非常高的丢包率,发送10k pack/s,有1.2k pack/s的丢包率(用sar观察到的)。
接收中断的那个核软中断很高(比单线程时高),但cpu利用率整体而言不高,为什么会出现严重丢包?

硬件是:Intel Xeon  E5504  @ 2.00GHz (2个物理cpu,每个cpu有4个核)
系统是:Linux 2.6.18

尝试过设置中断亲和,也尝试过将线程绑定到指定cpu,似乎都没有效果。
主要的代码如下:
  1. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  2. bind(sockfd, (struct sockaddr*)&addr, sizeof(addr);
  3.     vector<pthread_t> threads;
  4.     threads.resize(nthread);
  5.     for(int i = 0; i < nthread; ++i) {
  6.         pthread_create(&threads[i], NULL, echo, (void*)&sockfd);
  7.     }
复制代码
echo 函数如下:
  1.     while(1) {
  2.         rlen = recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&addr, &addrlen);
  3.         //sendto(sockfd, buf, rlen, 0, (struct sockaddr*)&addr, addrlen);
  4.     }
复制代码

论坛徽章:
0
2 [报告]
发表于 2010-03-05 12:28 |只看该作者
c++不懂,但是你的代码明显的问题读sockfd是不能放在线程里的,而且你现在用的是阻塞方式,改用select看看吧.把你的代码稍微改成c,你试试.

int sockfd;

void *echo( void *buf )
{
     int len;
     pthread_detach(pthread_self());
     len = recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&addr, &addrlen);
     /*any functions you will do next */
}

     
int main( int argc, char **argv )
{
fd_set fdset;
struct timeval tmout={0,0};
sockfd = socket(AF_INET, SOCK_DGRAM, 0);

bind(sockfd, (struct sockaddr*)&addr, sizeof(addr);

    pthread_t threads;
    while(1) {
        FD_ZERO(&fdset);
     FD_SET(sockfd,&fdset);
        if( select(sockfd+1,&fdset,NULL,NULL,&tmout) > 0 )
        {
             if( FD_ISSET( sockfd, &fdset ) )
                 pthread_create( &threads, NULL, echo, NULL);
        }   
    }
}

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
3 [报告]
发表于 2010-03-05 12:45 |只看该作者
打车求结果:
多个线程同时读取一个fd的时候是否需要加锁?

论坛徽章:
0
4 [报告]
发表于 2010-03-05 12:51 |只看该作者
多个线程都recv 一个fd , 这种做法行吗?
俺不知道。

多线程可能有线程切换。 但是多线程都是recv 一个 fd 的做法 没见过。

如果单线程应该就是最快的了

论坛徽章:
0
5 [报告]
发表于 2010-03-05 12:52 |只看该作者
本帖最后由 独臂剑客 于 2010-03-05 13:07 编辑

udp多线程,线程里收没什么问题的,不要多线程同时去收,你可以用一个主线程收取,处理分发给下面逻辑线程,如果你是作为服务器端,对于连接过来的客户端IP管理好就可以了。

为什么多程程发送会丢包,没有加锁保护乱了,内核不管你是UDP还是TCP对每个fd都只有一个缓冲区,你想一下,几个线程在发没有加锁向同一块内存狂发会不乱吗?fd里的缓冲早就全乱了。

如果你硬要用多线程,就要自己为某个客户端IP/端口映射一个缓冲啊,加上一些锁保护就不会乱了,效率也不会差。

论坛徽章:
0
6 [报告]
发表于 2010-03-05 13:46 |只看该作者
回复 2# 陆梦骏

这样的话,每次sockfd可读,就生成线程,那是否会产生大量线程?
而且,按这个代码,也是多个线程在一个sockfd上recv,是否有相同的问题呢?

论坛徽章:
0
7 [报告]
发表于 2010-03-05 13:56 |只看该作者
不好意思,我的代码中也有问题, recvfrom要么放到主函数中,要么在recvfrom前加pthread_mutex_lock,之后再pthread_mutex_unlock.

论坛徽章:
0
8 [报告]
发表于 2010-03-05 13:57 |只看该作者
回复 5# 独臂剑客

我写个一个测试程序,4个线程在一个sockfd上send,1个线程在一个sockfd上接收,并检查了发送、接收的数据报内容,没有发现乱序。

我认为多线程写同一个sockfd应该是没问题的。lseek+read/write多线程读写同一个fd有问题,而pwrite/pread多线程读写同一个fd却没问题。
同理,recvfrom/sendto是无须lseek的,和pwrite/pread类似,我认为在多线程环境中是没问题的。

我这里的关键问题是性能,为什么2个线程recv性能下降的如此之剧烈?

论坛徽章:
0
9 [报告]
发表于 2010-03-05 13:59 |只看该作者
回复 7# 陆梦骏

加锁应该是不必要的,对比pwrite/pread可知。
我简单查看过内核代码,内核对buffer/queue是有保护的。

论坛徽章:
0
10 [报告]
发表于 2010-03-05 14:05 |只看该作者
我认为问题可能是出在中断上,SMP下IRQ的问题。
我想请教一下,ifconfig观察到eth0的irq为:Interrupt:82
但 cat /proc/interrupts有如下输出:
  1. [root@ceshi download]# cat /proc/interrupts |grep eth
  2. 98:         52          0          0          0     696606    2992282      23359        402       PCI-MSI-X  eth0-0
  3. 106:         31        647       1555       4486       2530        805       3824          0       PCI-MSI-X  eth0-1
  4. 114:         37       2420        778       4728       1276         96       3842          0       PCI-MSI-X  eth0-2
  5. 122:         70      58760     191024       8620        577         31      42792          5       PCI-MSI-X  eth0-3
  6. 130:        116       2627        459        214         11        506        570          0       PCI-MSI-X  eth0-4
  7. 138:         60       4867     330606     693502       2818         49        805          0       PCI-MSI-X  eth0-5
  8. 146:  228342159   18383917     921461          0    2318849      24608     373264  191124170       PCI-MSI-X  eth0-6
  9. 154:         23      23204       1170       1580        592          6        450          5       PCI-MSI-X  eth0-7
复制代码
也就是与网卡相关的中断中没有82号中断(整个文件中也没有82号中断)。
而且,与中断相关的只有146这个中断发生,其余的eth0-x都没有发生。不知这是什么原因?

现在的情况是中断只发生在一个核上,我想让中断发生在多个核上,对比,但不能实现。
通过修改 /proc/irq/146/smp_affinity ,只能让146中断发生在某一个核上,不能实现均衡。
下载irqbalance也没有改变这个状况,中断始终如一的固定在某一核。那个大大帮一把?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP