免费注册 查看新帖 |

Chinaunix

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

Uperf的内部实现 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-26 11:35 |只看该作者 |倒序浏览
Uperf是一个网络性能测试工具。这篇文章主要讲解一下其中的实现细节,基本的用法清参考http://www.uperf.org。
Sun Fire T5140采用了两片UltraSPARC T2 Plus CPU,也就是说这一台1U的机器就能够有128个线程(2CPU * 8核 * 8线程)。其中内置了4口e1000g千兆网卡和两口的光线ixgbe 10G网卡。其中的10G网卡最多可以有32条发送I/O rings和32条接收I/O rings。如果CPU线程数量不够,网卡的高性能是绝对发挥不出来的。即使其他1U的机器能够使10G网卡达到线速,CPU占用率也是非常高的。要想证明这一点,强大的测试工具是少不了的。
Netperf/netserver是大家广为使用的测试工具,但是它只能测试单个线程/进程的性能。要想测试多进程的性能必须起多个实例,测试多线程更是做不到。而测试多连接性能带来的问题是,如何让这多个进程在建立完连接后同时发送/接收数据,如何同时结束。MAXQ解决了这个问题,但是有可能涉及专利问题,不便提及。如果不能同时发送/接收数据,先建立连接的进程占用了全部带宽,同理,后结束的进程也会占用全部带宽,使得最后累加的数据高于理论值,uperf正解决了这个问题。
Uperf可以实时更新当前测试的统计数据。要想实现这一点,uperf让各个进程/线程通过mmap共享结构体struct uperf_shm *global_shm,这样每个进程/线程更新完自己的数据后,master主线程就可以每过一秒统计所有进程/线程的数据。
        
               
                        
               
               
                        
               
               
                        
               
        
function runuperf
{
        export NETPERF_XML=netperf.xml
        export host1=11.0.1.153 dur=600 nth=1000 msg=8192 wnd=64K pro=tcp
        uperf -m ./$NETPERF_XML
}
上面的例子建立1000个线程进行数据发送测试。如果group的属性不是nthreads,而是nprocs则建立进程进行测试。如transaction的属性是iterations则该transaction执行若干次后停止;如果是duration,则执行若干秒后停止。刚才提到了uperf解决了各个线程/进程之间同步的问题,它主要是通过读写锁的机制来实现的。上面的实例一共有三个transactions,这三个transactions通过一个单项链表连接起来。第一个线程执行完它的第一个transactions后,将gloabl_shm->bar[0]->count原子加一。
(void) atomic_add_32_nv(&bar->count, 1);
然后pthread_rwlock_rdlock(&bar->barrier),而之前master主线程已经将写锁捕获,所以第一个线程会休眠。同理其他的进程/线程执行完第一个transaction后也会休眠。master每过一秒就检查一下bar->count是不是等于bar->limit。而bar->limit被初始化为当前transactions的进程/线程数,也就是检查是不是所有的进程/线程执行完了第一个transaction,如果为真,则释放写锁,唤醒所有进程/线程以及slaves执行下一个transaction。
在上面的实例中dur=600,也就是说第二个transaction执行10分钟。首先uperf给每个进程/线程注册一个global_shm->callouts表,这个表记录了每个进程/线程从现在算起什么时候退出。然后每个进程/线程进入一个while(0)循环,反复顺序执行每个flowop规定的动作,这里是发送操作。master主线程每过一秒就会检查一下各个进程/线程注册的时间是不是到了,如果到了就发送一个SIGUSR2信号,进程/线程收到后将gloabl_shm->bar->count原子加一,捕获读锁休眠。后面就同上了。
如果要禁掉Nagle's algorithm,需要在建立连接的时候在options中加入tcp_nodelay。用下面的dtrace脚本会发现,如果加上了tcp_nodelay,然后export msg=1,则包的大小是66个字节;如果不加,TCP/IP协议栈会将包聚合为90个字节大小的包后才发送出去,提高了性能,但是没有真实测到网卡发送小包的性能。
#!/usr/sbin/dtrace -qs
fbt:bge:bge_send:entry
/args[1]->b_rptr[4] == 0x1a && args[1]->b_rptr[5] == 0x14 && args[1]->b_rptr[12] == 0x08 && args[1]->b_rptr[13] == 0x0 && args[1]->b_rptr[23] == 0x6/
{
    printf("Message size: %d\n", args[1]->b_wptr - args[1]->b_rptr);
    printf("==================ETHER==================\n");
    printf("Destination: ");
    printf("%x:", args[1]->b_rptr[0]);
    printf("%x:", args[1]->b_rptr[1]);
    printf("%x:", args[1]->b_rptr[2]);
    printf("%x:", args[1]->b_rptr[3]);
    printf("%x:", args[1]->b_rptr[4]);
    printf("%x\t", args[1]->b_rptr[5]);
    printf("Source: ");
    printf("%x:", args[1]->b_rptr[6]);
    printf("%x:", args[1]->b_rptr[7]);
    printf("%x:", args[1]->b_rptr[8]);
    printf("%x:", args[1]->b_rptr[9]);
    printf("%x:", args[1]->b_rptr[10]);
    printf("%x\t", args[1]->b_rptr[11]);
    ether_type = (args[1]->b_rptr[12] & 0xff) b_rptr[13] & 0xff);
    printf("Ether type: ");
    printf("%4x\n", ether_type);
    printf("==================IP==================\n");
    printf("Version: ");
    printf("%d\t", (args[1]->b_rptr[14] & 0xf0) >> 4);
    printf("Header length: ");
    printf("%d\t", args[1]->b_rptr[14] & 0x0f);
    total_length = (args[1]->b_rptr[16] & 0xff) b_rptr[17] & 0xff);
    printf("Total length: ");
    printf("%d\n", total_length);
/*
    printf("%x\n", args[1]->b_rptr[18]);
    printf("%x\n", args[1]->b_rptr[19]);
    printf("%x\n", args[1]->b_rptr[20]);
    printf("%x\n", args[1]->b_rptr[21]);
*/
    printf("Time to Live: ");
    printf("%d\t", args[1]->b_rptr[22]);
    printf("Protocal (ICMP=1, TCP=6, UDP=17): ");
    printf("%d\t", args[1]->b_rptr[23]);
    printf("Header Checksum: ");
    checksum = (args[1]->b_rptr[24] & 0xff) b_rptr[25] & 0xff);
    printf("%x\n", checksum);
    printf("Source Address: ");
    printf("%d.", args[1]->b_rptr[26]);
    printf("%d.", args[1]->b_rptr[27]);
    printf("%d.", args[1]->b_rptr[28]);
    printf("%d\n", args[1]->b_rptr[29]);
    printf("Destination Address: ");
    printf("%d.", args[1]->b_rptr[30]);
    printf("%d.", args[1]->b_rptr[31]);
    printf("%d.", args[1]->b_rptr[32]);
    printf("%d\n", args[1]->b_rptr[33]);
    printf("==================TCP==================\n");
    printf("Source port: ");
    port = (args[1]->b_rptr[34] & 0xff) b_rptr[35] & 0xff);
    printf("%d\t", port);
    port = (args[1]->b_rptr[36] & 0xff) b_rptr[37] & 0xff);
    printf("Destination port: ");
    printf("%d\n", port);
    printf("Sequence number: ");
    seq = (args[1]->b_rptr[38] & 0xff) b_rptr[39] & 0xff)) b_rptr[40] & 0xff)) b_rptr[41] & 0xff);
    printf("%d\n", seq);
    printf("Acknowledgment number: ");
    ack = (args[1]->b_rptr[42] & 0xff) b_rptr[43] & 0xff) b_rptr[44] & 0xff) b_rptr[45] & 0xff);
    printf("%d\n", ack);
/*
    printf("%x\n", args[1]->b_rptr[46]);
    printf("%x\n", args[1]->b_rptr[47]);
*/
    printf("Window Size: ");
    window = (args[1]->b_rptr[48] & 0xff) b_rptr[49] & 0xff);
    printf("%d\n", window);
    printf("Checksum: ");
    checksum = (args[1]->b_rptr[50] & 0xff) b_rptr[51] & 0xff);
    printf("%x\n", checksum);
/*
    printf("%x\n", args[1]->b_rptr[52]);
    printf("%x\n", args[1]->b_rptr[53]);
*/
    printf("Data begin:\n");
    printf("%x ", args[1]->b_rptr[54]);
    printf("%x ", args[1]->b_rptr[55]);
    printf("%x ", args[1]->b_rptr[56]);
    printf("%x ", args[1]->b_rptr[57]);
    printf("%x ", args[1]->b_rptr[58]);
    printf("%x ", args[1]->b_rptr[59]);
    printf("%x ", args[1]->b_rptr[60]);
    printf("%x ", args[1]->b_rptr[61]);
    printf("%x ", args[1]->b_rptr[62]);
    printf("%x ", args[1]->b_rptr[63]);
    printf("%x ", args[1]->b_rptr[64]);
    printf("%x ", args[1]->b_rptr[65]);
    printf("%x ", args[1]->b_rptr[66]);
    printf("\n###########################end#########################\n");
}
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/23177/showart_2131372.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP