- 论坛徽章:
- 0
|
本帖最后由 bio_tt 于 2013-02-21 15:50 编辑
用epoll+拥有10个线程的线程池,作为web server,用ab 测试了一下
结果如下:
ab -c 1000 -t 5 *************:9000/
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking ******************* (be patient)
Completed 5000 requests
Completed 10000 requests
Finished 12995 requests
Server Software:
Server Hostname: **************
Server Port: 9000
Document Path: /
Document Length: 6888 bytes
Concurrency Level: 1000
Time taken for tests: 5.479 seconds
Complete requests: 12995
Failed requests: 0
Write errors: 0
Total transferred: 90095204 bytes
HTML transferred: 89523336 bytes
Requests per second: 2598.75 [#/sec] (mean)
Time per request: 384.800 [ms] (mean)
Time per request: 0.385 [ms] (mean, across all concurrent requests)
Transfer rate: 17594.91 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 132 598.6 4 3006
Processing: 1 38 26.3 31 290
Waiting: 0 26 23.2 21 280
Total: 2 171 606.5 35 3290
Percentage of the requests served within a certain time (ms)
50% 35
66% 41
75% 47
80% 54
90% 127
95% 203
98% 3072
99% 3095
100% 3290 (longest request)
感觉还是不够快。。
用strace跟踪了一下。
strace -c -p 12891
Process 12891 attached - interrupt to quit
Process 12891 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
68.45 1.469389 44 33654 2897 futex
11.89 0.255126 10 26142 epoll_ctl
10.99 0.236004 18 13297 226 accept
5.43 0.116617 223 524 epoll_wait
3.24 0.069480 5 13071 fcntl
------ ----------- ----------- --------- --------- ----------------
100.00 2.146616 86688 3123 total
发现时间主要耗在 futex上。。70%了。。就大侠支招改进。。
主要是工作线程间使用了pthread_mutex_lock.
贴点代码:
struct data{
int fd;
struct data *next;
};
struct data *all,*main1;
int epfd;
struct epoll_event ev;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t flag=PTHREAD_COND_INITIALIZER;
void setnonblocking(int sock)
{
if(fcntl(sock,F_SETFL,O_NONBLOCK)<0)
{
printf("fcntl set error1\n" ;exit(1);
}
}
void do_work()
{
while(1)
{
int check_all=0;
int client_sockfd;
pthread_mutex_lock(&lock);
while(all == NULL)
{
pthread_cond_wait(&flag,&lock);
}
struct data *tmp1=all;
client_sockfd=tmp1->fd;
all=tmp1->next;
free(tmp1);
int flaga;
flaga=fcntl(client_sockfd,F_GETFL,0);
flaga &=~O_NONBLOCK;
if(fcntl(client_sockfd,F_SETFL,flaga) == -1)
perror("fcntl" ;
pthread_mutex_unlock(&lock);
读,然后发数据
}
}
void main(int argc,char *argv[])
{
daemon();
struct sigaction sa;
sa.sa_handler=SIG_IGN;
sigaction(SIGPIPE,&sa,0);
int len,nfds,opts,listenfd,client,sockfd;
struct sockaddr_in server_addr,client_addr;
struct epoll_event events[1000];
listenfd=socket(AF_INET,SOCK_STREAM,0);
setnonblocking(listenfd);
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(9000);
server_addr.sin_addr.s_addr=inet_addr("114.255.218.163" ;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,1,sizeof(int));
int nRecvBuf=32*1024;
setsockopt(listenfd,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
bind(listenfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
listen(listenfd,50);
epfd=epoll_create(10000);
ev.data.fd=listenfd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
int i,maxi=0;
pthread_t go[10];
for(i=0;i<10;i++)
{
pthread_create(&go,NULL,(void *)do_work,NULL);
pthread_detach(go);
}
for(;
{
nfds=epoll_wait(epfd,events,1000,500);
for(i=0;i<nfds;i++)
{
if(events.data.fd == listenfd)
{
socklen_t client_size=sizeof(client_addr);
while(1)
{
client=accept(listenfd,(struct sockaddr *)&client_addr,&client_size);
if(client <0)
{
break;
}
setnonblocking(client);
ev.data.fd=client;
epoll_ctl(epfd,EPOLL_CTL_ADD,client,&ev);
}
}
else{
if(events.events == EPOLLERR)
{
int readsock=events.data.fd;
ev.data.fd=readsock;
epoll_ctl(epfd,EPOLL_CTL_DEL,readsock,&ev);
close(readsock);
}
if(events.events == EPOLLIN)
{
int readsock=events.data.fd;
pthread_mutex_lock(&lock);
main1=(struct data *)malloc(sizeof(struct data));
if(main1 == NULL)
{
printf("main1 can not malloc\n" ;exit(1);
}
main1->fd=readsock;
main1->next=NULL;
if(all == NULL)
all=main1;
else{
struct data *tmp1;
tmp1=all;
while(tmp1->next !=NULL)
tmp1=tmp1->next;
tmp1->next=main1;
}
pthread_cond_signal(&flag);
ev.data.fd=readsock;
epoll_ctl(epfd,EPOLL_CTL_DEL,readsock,&ev);
pthread_mutex_unlock(&lock);
}
}
}
}
}
|
|