1,摘要:测试send和sendmsg的性能,影响这两个函数性能主要有发送的字节大小,增加循环次数,从100到10000000(千万)
2,基本信息
cat /proc/cpuinfo查看CPU信息,如下:
Intel(R) Xeon(R) CPU E5-2698 v3 @ 2.30GHz
cat /proc/version 查看操作系统内核版本,如下:
Linux version 3.10.0-327.el7.x86_64
cat /proc/meminfo查看内存信息,如下:
MemTotal: 131748016 kB
MemFree: 42526620 kB
MemAvailable: 60623924 kB
3,send性能测试
服务器端 : nc -lu 8888
客服端:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include<time.h> #include <sys/times.h> #include <unistd.h> //#define BUFSIZ 1024 #define recycle 1000000 static inline uint64_t rte_rdtsc(void) { union { uint64_t tsc_64; struct { uint32_t lo_32; uint32_t hi_32; }; }tsc; asm volatile("rdtsc": "=a" (tsc.lo_32), "=d" (tsc.hi_32)); return tsc.tsc_64; } int recycleSet[]={100,500,1000,5000,10000,50000,100000,500000,1000000,5000000,10000000}; int bufsizeSet[]={128,256,512,1024,2048,3072,4096}; int main(int argc,char *argv[]) { /*if(argc<3) { printf("paramaters error! ./socet_sendmsg 1000 1024"); return -1; } int recycle_times=atoi(argv[1]); int buf_len=atoi(argv[2]); */ int sockfd,numbytes; //char buf[BUFSIZ]; int sc_clk_tck; sc_clk_tck = sysconf(_SC_CLK_TCK); sc_clk_tck = sysconf(_SC_CLK_TCK); struct sockaddr_in their_addr; //printf("break! sc_clk_tck=%d\n",sc_clk_tck); while((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1); //printf("We get the sockfd~\n"); their_addr.sin_family = AF_INET; their_addr.sin_port = htons(8888); their_addr.sin_addr.s_addr=inet_addr("192.168.10.8"); bzero(&(their_addr.sin_zero), 8); while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1); // printf("Get the Server~Cheers!\n"); 濉濞绔俊姣 // numbytes = recv(sockfd, buf, BUFSIZ,0);//妤娑? // buf[numbytes]='\0'; // printf("%s",buf); //clock_t start_time,end_time; // start_time=clock(); int buf_i=0; for(buf_i=0;buf_i<7;buf_i++){ int buf_len=bufsizeSet[buf_i]; char *buf=(char *)calloc(buf_len,sizeof(char)); int i=0; for(i=0;i<buf_len;i++) { buf[i]='a' + rand()%26; } buf[buf_len]='\0'; int recycle_i=0; for(recycle_i=0;recycle_i<11;recycle_i++){ int recycle_times=recycleSet[recycle_i]; struct timeval start_time,end_time; gettimeofday(&start_time,NULL); uint64_t start=rte_rdtsc(); for(i=0;i<recycle_times;i++) { numbytes = send(sockfd, buf, strlen(buf), 0); //numbytes=recv(sockfd,buf,BUFSIZ,0); //buf[numbytes]='\0'; //printf("send:%d\n",numbytes); } uint64_t end=rte_rdtsc(); //end_time=clock(); gettimeofday(&end_time,NULL); uint64_t duration=end-start; double duration_time=1000000*(end_time.tv_sec-start_time.tv_sec)+(end_time.tv_usec-start_time.tv_usec); //printf("recycle_times=%d duration=%f numbytes=%d duration_rte=%f\n",recycle_times,duration_time,numbytes,duration/2.2); printf("%d,%d,%d, %f ,%f,%f\n",recycle_times,numbytes,buf_len,duration_time,duration/2.2,duration_time*1.0/recycle_times); } } close(sockfd); return 0; }
4,sendmsg性能测试
服务器端:
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> /************************************************************************************************************************ *************************************************************************************************************************/ int main(int argc, char *argv[]) { int fd, new_fd, struct_len, numbytes,i; struct sockaddr_in server_addr; struct sockaddr_in client_addr; char buff[BUFSIZ]; //struct msghdr msg; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8888); server_addr.sin_addr.s_addr = INADDR_ANY; // bzero(&(server_addr.sin_zero), 8); struct_len = sizeof(struct sockaddr_in); while((fd = socket(AF_INET,SOCK_DGRAM,0)) == -1); if (bind(fd, (struct sockaddr*)(&server_addr), struct_len) < 0) { fprintf(stderr, "bind fail\n"); exit(EXIT_FAILURE); } printf("Bind Success!\n"); // fd = socket(AF_INET, SOCK_DGRAM, 0); /*while(bind(fd, (struct sockaddr *)&server_addr, struct_len) == -1); printf("Bind Success!\n"); while(listen(fd, 100) == -1); printf("Listening....\n"); printf("Ready for Accept,Waitting...\n"); new_fd = accept(fd, (struct sockaddr *)&client_addr, &struct_len); */ //printf("Get the Client.\n"); // numbytes = send(new_fd,"Welcome to my server\n",21,0); while(1) { printf("recemsg\n"); struct msghdr msg; bzero(&msg,sizeof(struct msghdr)); msg.msg_name =&client_addr; msg.msg_namelen =sizeof(struct sockaddr_in); struct iovec io; io.iov_base =buff; io.iov_len =BUFSIZ; msg.msg_iov = &io; msg.msg_iovlen = 1; numbytes = recvmsg(fd,&msg,0); char * temp = msg.msg_iov[0].iov_base;//获取得到的数据 temp[numbytes] = '\0';//为数据末尾添加结束符 // printf("get %d message:%s", numbytes,temp); printf("get %d \n", numbytes); } // close(new_fd); close(fd); return 0; }
客服端:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include<time.h> #include <sys/times.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> //#define BUFSIZ 1024 #define recycle 1000000 static inline uint64_t rte_rdtsc(void) { union { uint64_t tsc_64; struct { uint32_t lo_32; uint32_t hi_32; }; }tsc; asm volatile("rdtsc": "=a" (tsc.lo_32), "=d" (tsc.hi_32)); return tsc.tsc_64; } int recycleSet[]={100,500,1000,5000,10000,50000,100000,500000,1000000,5000000,10000000}; int bufsizeSet[]={128,256,512,1024,2048,3072,4096}; int main(int argc,char *argv[]) { /*if(argc<3) { printf("paramaters error! ./socet_sendmsg 1000 1024"); return -1; } int recycle_times=atoi(argv[1]); int buf_len=atoi(argv[2]); */ int sockfd,numbytes; //char buf[BUFSIZ]; int sc_clk_tck; sc_clk_tck = sysconf(_SC_CLK_TCK); struct sockaddr_in their_addr; //printf("break! sc_clk_tck=%d\n",sc_clk_tck); while((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1); //printf("We get the sockfd~\n"); bzero(&their_addr, sizeof(their_addr)); their_addr.sin_family = AF_INET; their_addr.sin_port = htons(8888); their_addr.sin_addr.s_addr=inet_addr("192.168.10.8"); //their_addr.sin_addr.s_addr=htonl(INADDR_ANY); //bzero(&(their_addr.sin_zero), 8); // while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1); // printf("Get the Server~Cheers!\n"); // numbytes = recv(sockfd, buf, BUFSIZ,0);//接收服务器端信息 // buf[numbytes]='\0'; // printf("%s",buf); //clock_t start_time,end_time; // start_time=clock(); int buf_i=0; for(buf_i=0;buf_i<7;buf_i++){ int buf_len=bufsizeSet[buf_i]; char *buf=(char *)calloc(buf_len,sizeof(char)); int i=0; for(i=0;i<buf_len;i++) { buf[i]='a' + rand()%26; } buf[buf_len]='\0'; struct msghdr msg; bzero(&msg,sizeof(struct msghdr)); //msg.msg_name = NULL; msg.msg_name = &their_addr; msg.msg_namelen = sizeof(struct sockaddr_in); struct iovec io; io.iov_base = buf; io.iov_len = buf_len; msg.msg_iov = &io; msg.msg_iovlen = 1; int recycle_i=0; for(recycle_i=0;recycle_i<11;recycle_i++){ int recycle_times=recycleSet[recycle_i]; struct timeval start_time,end_time; gettimeofday(&start_time,NULL); uint64_t start=rte_rdtsc(); for(i=0;i<recycle_times;i++) { //numbytes = send(sockfd, buf, strlen(buf), 0); numbytes = sendmsg(sockfd, &msg, 0); //numbytes=recv(sockfd,buf,BUFSIZ,0); //buf[numbytes]='\0'; //printf("send:%d\n",numbytes); } uint64_t end=rte_rdtsc(); //end_time=clock(); gettimeofday(&end_time,NULL); uint64_t duration=end-start; double duration_time=1000000*(end_time.tv_sec-start_time.tv_sec)+(end_time.tv_usec-start_time.tv_usec); //printf("recycle_times=%d duration=%f numbytes=%d duration_rte=%f\n",recycle_times,duration_time,numbytes,duration/2.2); printf("%d,%d,%d, %f ,%f,%f\n",recycle_times,numbytes,buf_len,duration_time,duration/2.2,duration_time*1.0/recycle_times); } } close(sockfd); return 0; }
5,send测试数据表
6,sendmsg测试数据表
7,用gettimeofday测试性能基本逻辑(gettimeofday和滴答数转化成时间基本差不多)
单位为:微秒
struct timeval start_time,end_time;
gettimeofday(&start_time,NULL);
uint64_t start=rte_rdtsc();
函数调用
uint64_t end=rte_rdtsc();
//end_time=clock();
gettimeofday(&end_time,NULL);
uint64_t duration=end-start;
double duration_time=1000000*(end_time.tv_sec-start_time.tv_sec)+(end_time.tv_usec-start_time.tv_usec);
8,send和sendmsg性能测试比较(循环一千万次,算出一次时间开销(微秒))
结论:
1,send和sendmsg的性能基本一样
2,性能随字节成正比,比如128B~1.55微秒 ,256B~2.57微秒,1024B~8.72微秒,4096B~34.22微秒