• send和sendmsg性能测试


    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
    ",sc_clk_tck);
        while((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1);
        //printf("We get the sockfd~
    ");
        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!
    ");           濉濞绔�俊姣
       // numbytes = recv(sockfd, buf, BUFSIZ,0);//妤娑?
       // buf[numbytes]='';
       // 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]='';
            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]='';
           //printf("send:%d
    ",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
    ",recycle_times,duration_time,numbytes,duration/2.2);
       printf("%d,%d,%d, %f ,%f,%f
    ",recycle_times,numbytes,buf_len,duration_time,duration/2.2,duration_time*1.0/recycle_times);
            }
       }
        close(sockfd);
        return 0;
    }

    4,sendmsg性能测试(iovlen=1)

    服务器端:

    #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
    ");  
          exit(EXIT_FAILURE);  
       }  
       printf("Bind Success!
    ");
       // fd = socket(AF_INET, SOCK_DGRAM, 0);
        /*while(bind(fd, (struct sockaddr *)&server_addr, struct_len) == -1);
        printf("Bind Success!
    ");
        while(listen(fd, 100) == -1);
        printf("Listening....
    ");
        printf("Ready for Accept,Waitting...
    ");
        new_fd = accept(fd, (struct sockaddr *)&client_addr, &struct_len);
        */
    	//printf("Get the Client.
    ");
       // numbytes = send(new_fd,"Welcome to my server
    ",21,0); 
        while(1)
        {
    		printf("recemsg
    ");
    		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] = '';//为数据末尾添加结束符
           // printf("get %d message:%s", numbytes,temp);
    		printf("get %d 
    ", 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
    ",sc_clk_tck);
        while((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1);
        //printf("We get the sockfd~
    ");
    	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!
    ");
       // numbytes = recv(sockfd, buf, BUFSIZ,0);//接收服务器端信息  
       // buf[numbytes]='';  
       // 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]='';
    	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]=''; 
           //printf("send:%d
    ",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
    ",recycle_times,duration_time,numbytes,duration/2.2);
       printf("%d,%d,%d, %f ,%f,%f
    ",recycle_times,numbytes,buf_len,duration_time,duration/2.2,duration_time*1.0/recycle_times);
    	}
       }
        close(sockfd);
        return 0;
    }
    

    4,sendmsg性能测试(iovlen=4)

    服务器端:

    #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,5120,6144,7168,8192,9216,15000,150000};
    #define BUF_CNT 14
    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
    ",sc_clk_tck);
        while((sockfd = socket(AF_INET,SOCK_DGRAM,0)) == -1);
        //printf("We get the sockfd~
    ");
    	bzero(&their_addr, sizeof(their_addr));
        their_addr.sin_family = AF_INET;
        their_addr.sin_port = htons(9999);
        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!
    ");
       // numbytes = recv(sockfd, buf, BUFSIZ,0);//接收服务器端信息  
       // buf[numbytes]='';  
       // printf("%s",buf);
    	
    	//clock_t start_time,end_time;
       // start_time=clock();
       int buf_i=0;
       for(buf_i=0;buf_i<14;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]='';
    	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[4];
    	io[0].iov_base = buf;
    	io[0].iov_len = buf_len;
    	io[1].iov_base = buf;
    	io[1].iov_len = buf_len;
    	io[2].iov_base = buf;
    	io[2].iov_len = buf_len;
    	io[3].iov_base = buf;
    	io[3].iov_len = buf_len;
    	
    	msg.msg_iov = io;
    	msg.msg_iovlen =4;	 
    	int recycle_i=0;
    	for(recycle_i=8;recycle_i<9;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);MSG_DONTWAIT
    		numbytes = sendmsg(sockfd, &msg, 0);
                //numbytes=recv(sockfd,buf,BUFSIZ,0);  
            //buf[numbytes]=''; 
           //printf("send:%d
    ",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
    ",recycle_times,duration_time,numbytes,duration/2.2);
       printf("%d,%d,%d, %f ,%f,%f
    ",recycle_times,numbytes,buf_len,duration_time,duration/2.3,duration_time*1.0/recycle_times);
    	}
       }
        close(sockfd);
        return 0;
    }
    

      客户端:

    #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>
    /************************************************************************************************************************
    1、int socket(int family,int type,int protocol)
    family:
        指定使用的协议簇:AF_INET(IPv4) AF_INET6(IPv6) AF_LOCAL(UNIX协议) AF_ROUTE(路由套接字) AF_KEY(秘钥套接字)
    type:
        指定使用的套接字的类型:SOCK_STREAM(字节流套接字) SOCK_DGRAM
    protocol:
        如果套接字类型不是原始套接字,那么这个参数就为0
    2、int bind(int sockfd, struct sockaddr *myaddr, int addrlen)
    sockfd:
        socket函数返回的套接字描述符
    myaddr:
        是指向本地IP地址的结构体指针
    myaddrlen:
        结构长度
    struct sockaddr{
        unsigned short sa_family; //通信协议类型族AF_xx
        char sa_data[14];  //14字节协议地址,包含该socket的IP地址和端口号
    };
    struct sockaddr_in{
        short int sin_family; //通信协议类型族
        unsigned short int sin_port; //端口号
        struct in_addr sin_addr; //IP地址
        unsigned char si_zero[8];  //填充0以保持与sockaddr结构的长度相同
    };
    3、int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen)
    sockfd:
        socket函数返回套接字描述符
    serv_addr:
        服务器IP地址结构指针
    addrlen:
        结构体指针的长度
    4、int listen(int sockfd, int backlog)
    sockfd:
        socket函数绑定bind后套接字描述符
    backlog:
        设置可连接客户端的最大连接个数,当有多个客户端向服务器请求时,收到此值的影响。默认值20
    5、int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen)
    sockfd:
        socket函数经过listen后套接字描述符
    cliaddr:
        客户端套接字接口地址结构
    addrlen:
        客户端地址结构长度
    6、int send(int sockfd, const void *msg,int len,int flags)
    7、int recv(int sockfd, void *buf,int len,unsigned int flags)
    sockfd:
        socket函数的套接字描述符
    msg:
        发送数据的指针
    buf:
        存放接收数据的缓冲区
    len:
        数据的长度,把flags设置为0
    *************************************************************************************************************************/
    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*10];
    	printf("BUFFSIZE %d
    ",BUFSIZ);
    	//struct msghdr msg;  
    	bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(9999);
        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)  
       {  
    		printf("bind error
    ");
    		return -1;
       }
       printf("Bind Success!
    ");
       // fd = socket(AF_INET, SOCK_DGRAM, 0);
        /*while(bind(fd, (struct sockaddr *)&server_addr, struct_len) == -1);
        printf("Bind Success!
    ");
        while(listen(fd, 100) == -1);
        printf("Listening....
    ");
        printf("Ready for Accept,Waitting...
    ");
        new_fd = accept(fd, (struct sockaddr *)&client_addr, &struct_len);
        */
    	//printf("Get the Client.
    ");
       // numbytes = send(new_fd,"Welcome to my server
    ",21,0); 
       int cnt=0;
        while(1)
        {
    		printf("recemsg
    ");
    		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*100;
    		 msg.msg_iov = &io;  
    		msg.msg_iovlen = 5; 
    		numbytes = recvmsg(fd,&msg,0);
             char * temp = msg.msg_iov[0].iov_base;//获取得到的数据
            temp[numbytes] = '';//为数据末尾添加结束符
           // printf("get %d message:%s", numbytes,temp);
    	   if(numbytes>0)
    		   cnt++;
    		printf("get %d  cnt %d
    ", numbytes,cnt);
        }
       // close(new_fd);
        close(fd);
        return 0;
    }
    

      

    6,send测试数据表

    7,sendmsg测试数据表(iovlen=1)

     7,sendmsg测试数据表(iovlen=4)

    8,比较send,sendmsg(iovlen=1),sendmsg(iovlen=4)

     9,用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微秒

    3,sendmsg(iovlen=1)和sendmsg(iovlen=4)的在发送相同字节情况下,性能也是4倍,sendmsg在性能上并没得到优化

  • 相关阅读:
    QT QFileDialog::getOpenFileName 对文件名进行过滤
    LeetCode 17 Letter Combinations of a Phone Number
    安装terminator与配置
    导出 .bag 文件 pointcloud 话题 到 pcd文件
    Spring SpringMVC文件上传错误(二)
    Spring SpringMVC文件上传错误(一)
    Spring配置文件中的file与classpath
    常用python的标准库
    Django之天天生鲜项目
    Django之富文本编辑器
  • 原文地址:https://www.cnblogs.com/woshare/p/9079965.html
Copyright © 2020-2023  润新知