分享

用EPOLL进行压力测试

 昵称10504424 2013-12-05

在以前的博客中提到的一个服务端,在以前压力测试的过程中,发现单核CPU最多能达到1000TPS

还以为是服务端性能不够好,所以一直想着怎么去优化它。

但优化的思路明显不多,所以就考虑换一种压力测试的方法,事实证明这个想法是对的。

以前的压力测试方法 :

思路是用多进程来实现并发,代码如上所示;

现在的压力测试方法:

复制代码
//客户端程序    

/******* 客户端程序 client.c ************/    
#include  <stdio.h>   
#include  <stdlib.h>   
#include <sys/types.h>   
#include <sys/socket.h>   
#include  <string.h>   
#include  <netdb.h>   
#include <netinet/in.h>   
#include <errno.h>   
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/epoll.h>


static struct sockaddr_in server_addr;    
static int epoll_fd;
static int currency,total_req;    
static struct epoll_event* events;

int setnonblock(int fd)
{
    int flags;
    flags = fcntl(fd, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(fd, F_SETFL, flags);
}

void new_conn()
{
        if(--total_req < 0)return;
    int sockfd;
    /* 客户程序开始建立 sockfd描述符 */    
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)    
    {    
        fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));    
        return ;
    }    
    setnonblock(sockfd);

    //让epoll接管
    struct epoll_event event;
    event.data.fd=sockfd;
    event.events = EPOLLOUT|EPOLLIN;
    epoll_ctl(epoll_fd,EPOLL_CTL_ADD, sockfd,&event);

    /* 客户程序发起连接请求 */    
    if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)    
    {    
        if(errno == EINPROGRESS)
            return;
        fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));    
        return;
    }    


}
int main(int argc, char *argv[])    
{    
    struct hostent *host;    
    if((host=gethostbyname(argv[1]))==NULL)    
    {    
        fprintf(stderr,"Gethostname error\n");    
        exit(1);    
    }    

    int portnumber,nbytes;    
    if((portnumber=atoi(argv[2]))<0)    
    {    
        fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);    
        exit(1);    
    }    

    /* 客户程序填充服务端的资料 */    
    bzero(&server_addr,sizeof(server_addr));    
    server_addr.sin_family=AF_INET;    
    server_addr.sin_port=htons(portnumber);    
    server_addr.sin_addr=*((struct in_addr *)host->h_addr);    

    //并发数和总的请求数
    currency = atoi(argv[3]);
    total_req = currency * atoi(argv[4]);

    if((epoll_fd=epoll_create(1000))==-1)    
    {    
        fprintf(stderr,"epoll create Error:%s\a\n",strerror(errno));    
        exit(1);    
    }    

    events = calloc(1000,sizeof(struct epoll_event));

    //初始化并发数个连接
    int i;
    for(i=0;i<currency;i++)new_conn(); 


    while(1)
    {
        fprintf(stderr,"while\n");
        int n,j;
        n = epoll_wait(epoll_fd, events, 1000, -1);
        for(j=0;j<n;j++)
        {
            if(events[j].events & EPOLLOUT)
            {
                                fprintf(stderr, "can write\n",n);
                int fd = events[j].data.fd;
                                int optval;
                                socklen_t optlen = sizeof(optval);
                                if(getsockopt(fd,SOL_SOCKET,SO_ERROR,&optval, &optlen) == -1)
                {
                    fprintf(stderr, "getsockopt error\n",n);
                } else if(optval != 0) {
                    fprintf(stderr, "connect error\n",n);
                    continue;
                };
                struct epoll_event event;
                event.data.fd=fd;
                event.events = EPOLLIN;
                epoll_ctl(epoll_fd,EPOLL_CTL_MOD, fd,&event);
                write(fd, "hello", strlen("hello"));
            }
            else if(events[j].events & EPOLLIN)
            {
                fprintf(stderr, "can read\n",n);
                int fd = events[j].data.fd;
                char buf[100];
                int n=read(fd,buf,100);
                close(fd);
                new_conn();
                if(n==-1)
                {
                    fprintf(stderr,"read Error:%s\a\n",strerror(errno));    
                    continue;
                }
                buf[n]=0;
                printf("return %s\n",buf);
            }else 
            {
                                fprintf(stderr, "can else\n",n);
                printf("%d %d %d %d %d %d %u\n",events[j].events, EPOLLIN, EPOLLOUT, EPOLLPRI,EPOLLERR, EPOLLHUP,EPOLLET);
                                close(events[j].data.fd);
            }
        }
    } 
}  
思路就是用单进程来测试,用EPOOL来实现并发
代码也可下载:http://pan.baidu.com/s/1vdQqB

性能对比:
环境:单核CPU,两台机器,一台服务端,一台客户端
多进程:690TPS
EPOLL:6435TPS
性能提高了十倍!


分析:
在单个机器上,使用多进程,资源消耗很大,不可能达到太大的并发
而使用EPOLL,单进程同时监听多个socket,可以达到较高并发

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多