免费注册 查看新帖 |

Chinaunix

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

请问epoll应该怎么用才能体现出高性能? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-11 23:08 |只看该作者 |倒序浏览
我在网上抄了一段使用epoll的代码,大概的流程就是
主线程 --> 阻塞在accept()上,一旦有连接过来就放到epoll监听事件队列中去
其他线程 --> 各自从epoll的队列里面取出连接进行处理.

现在问题是,我在一台 双至强 E5220,共16核,4G 内存的机器上跑,在另一台一样的机器上用http_load压,最多只能跑到 1w fetchs/s

  1. ./http_load -p 1000 -f 1000000 ./url 2>/dev/null               
  2. 1000000 fetches, 1000 max parallel, 4.01402e+09 bytes, in 96.1637 seconds
  3. 4014.02 mean bytes/connection
  4. 10398.9 fetches/sec, 4.17415e+07 bytes/sec
复制代码
请问这个在代码层面上应该怎么改进? 或者说,这种多路事件处理的模型根本就是不合理的?
  1. #include <iostream>
  2. #include <cstring>
  3. #include <string>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <errno.h>
  8. #include <pthread.h>
  9. #include <sys/epoll.h>
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <signal.h>

  13. #include "http_response.h"

  14. using namespace std;

  15. inline void log_error(char *c);
  16. int read_write(int *sock_fd);
  17. void do_accept(int *epoll_fd);

  18. const int THREAD_NUMBER = 8;
  19. const int MAX_FDS = 4096;
  20. const int EPOLL_TIMEOUT = 1000;


  21. int sock_fd;

  22. pthread_mutex_t fd_mutex;

  23. int main(void){
  24.         int rc = 0;
  25.         sock_fd = socket(PF_INET, SOCK_STREAM, 0);
  26.         if(-1 == sock_fd) log_error("socket error");

  27.         /*
  28.         rc = fcntl(sock_fd, F_SETFL, O_NONBLOCK);
  29.         if(rc == -1) log_error("fcntl set nonblock error");
  30.         */

  31.         int val = 1;
  32.         rc = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
  33.         if(rc != 0) log_error("setsockopt error");

  34.         struct sockaddr_in addr;
  35.         memset(&addr, 0, sizeof(addr));

  36.         addr.sin_port = htons(1819);
  37.         addr.sin_family = AF_INET;
  38.         addr.sin_addr.s_addr = htonl(INADDR_ANY);

  39.         rc = bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr));
  40.         if(rc != 0) log_error("bind error");

  41.         rc = listen(sock_fd, 1024);
  42.         if(rc != 0) log_error("listen error");

  43.         // 创建epoll描述符
  44.         int epoll_fd = epoll_create(MAX_FDS);
  45.         if(epoll_fd == -1) log_error("epoll_create error");

  46.         pthread_t th[THREAD_NUMBER];
  47.         pthread_attr_t attr;

  48.         pthread_attr_init(&attr);

  49.         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  50.         pthread_mutex_init(&fd_mutex, NULL);

  51.         for(int i = 0; i < THREAD_NUMBER; ++i)
  52.                 pthread_create(&th[i], &attr, (void*(*)(void*))read_write, &epoll_fd);

  53.         do_accept(&epoll_fd);

  54.         return 0;
  55. }

  56. inline void log_error(char *c){
  57.         cout<<c<<": "<<strerror(errno)<<endl;
  58.         _exit(-1);
  59. }

  60. void do_accept(int *epoll_fd){
  61.         int rc = 0;
  62.         int connect_fd = 0;
  63.         struct epoll_event ev;

  64.         while(1){
  65.         //        pthread_mutex_lock(&fd_mutex);
  66.                 connect_fd = accept(sock_fd, NULL, NULL);
  67.         //        pthread_mutex_unlock(&fd_mutex);

  68.                 if(connect_fd > 0){
  69.                         rc = fcntl(connect_fd, F_SETFL, O_NONBLOCK);
  70.                         if(rc == -1){log_error("fcntl set nonblock error");}

  71.                         ev.data.fd = connect_fd;
  72.                         ev.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLERR | EPOLLHUP | EPOLLPRI;

  73.                         rc = epoll_ctl(*epoll_fd, EPOLL_CTL_ADD, connect_fd, &ev);
  74.                         if(rc == -1) { log_error("epoll_ctl add socket fd error");}
  75.                 }
  76.         }
  77. }

  78. int read_write(int *epoll_fd){
  79.         int count = 0;

  80.         struct epoll_event ev, events[MAX_FDS];

  81.         char r_buffer[4096];
  82.         char w_buffer[4096] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\nConnection: close\r\nContent-Type: text/html\r\n\r\nHello";

  83.         #define data_fd (events[i].data.fd)

  84.         while(1){
  85.                 count = epoll_wait(*epoll_fd, events, MAX_FDS, 1000);

  86.                 for(int i = 0; i < count; ++i){
  87.                         if(events[i].events&EPOLLIN){
  88.                                 read(data_fd, r_buffer, sizeof(r_buffer));

  89.                                 ev.data.fd = data_fd;
  90.                                 ev.events = EPOLLET | EPOLLOUT;
  91.                                 epoll_ctl(*epoll_fd, EPOLL_CTL_MOD, data_fd, &ev);
  92.                         }
  93.                         else if(events[i].events&EPOLLOUT){
  94.                                 write(data_fd, w_buffer, sizeof(w_buffer));

  95.                                 ev.data.fd = data_fd;
  96.                                 epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, data_fd, &ev);
  97.                                 close(data_fd);
  98.                         }
  99.                         else{
  100.                                 ev.data.fd = data_fd;
  101.                                 epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, data_fd, &ev);

  102.                                 close(data_fd);
  103.                         }
  104.                 }
  105.         }

  106.         return 0;
  107. }

复制代码

论坛徽章:
0
2 [报告]
发表于 2010-11-11 23:54 |只看该作者
先看看瓶颈在什么地方,再针对性进行优化,在很多环境下,其实epoll和select、poll差不多,其他地方的处理的优化空间大多了

论坛徽章:
0
3 [报告]
发表于 2010-11-12 08:44 |只看该作者
CPU的使用率一直都很高,长时间维持在100%左右
另外,拿strace -c -p PID看的时候, 70%的时间被用在了epoll_ctl上了,30%多的是在accept上面

我拿lighttpd也试过这样的测试,如果只是跑这样hello world的代码
lighttpd,8个worker跑的时候cpu只会在40%左右,而http_load的测试结果能达到
1.5w fetches/sec

论坛徽章:
0
4 [报告]
发表于 2010-11-12 10:42 |只看该作者
epoll对与select的区别在于大量长连接时不需要去轮讯每个文件描述符,所以只有在存在大量长连接时,epoll才有它的优势.

论坛徽章:
0
5 [报告]
发表于 2010-11-12 12:14 |只看该作者
那你的意思是我这个在代码的层面上没有调优的空间了?

论坛徽章:
0
6 [报告]
发表于 2010-11-12 12:29 |只看该作者
要调优首先需要找到短板 用oprofile或gprof分析一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP