- 论坛徽章:
- 0
|
我在网上抄了一段使用epoll的代码,大概的流程就是
主线程 --> 阻塞在accept()上,一旦有连接过来就放到epoll监听事件队列中去
其他线程 --> 各自从epoll的队列里面取出连接进行处理.
现在问题是,我在一台 双至强 E5220,共16核,4G 内存的机器上跑,在另一台一样的机器上用http_load压,最多只能跑到 1w fetchs/s
- ./http_load -p 1000 -f 1000000 ./url 2>/dev/null
- 1000000 fetches, 1000 max parallel, 4.01402e+09 bytes, in 96.1637 seconds
- 4014.02 mean bytes/connection
- 10398.9 fetches/sec, 4.17415e+07 bytes/sec
复制代码 请问这个在代码层面上应该怎么改进? 或者说,这种多路事件处理的模型根本就是不合理的?- #include <iostream>
- #include <cstring>
- #include <string>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <errno.h>
- #include <pthread.h>
- #include <sys/epoll.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <signal.h>
- #include "http_response.h"
- using namespace std;
- inline void log_error(char *c);
- int read_write(int *sock_fd);
- void do_accept(int *epoll_fd);
- const int THREAD_NUMBER = 8;
- const int MAX_FDS = 4096;
- const int EPOLL_TIMEOUT = 1000;
- int sock_fd;
- pthread_mutex_t fd_mutex;
- int main(void){
- int rc = 0;
- sock_fd = socket(PF_INET, SOCK_STREAM, 0);
- if(-1 == sock_fd) log_error("socket error");
- /*
- rc = fcntl(sock_fd, F_SETFL, O_NONBLOCK);
- if(rc == -1) log_error("fcntl set nonblock error");
- */
- int val = 1;
- rc = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
- if(rc != 0) log_error("setsockopt error");
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_port = htons(1819);
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- rc = bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr));
- if(rc != 0) log_error("bind error");
- rc = listen(sock_fd, 1024);
- if(rc != 0) log_error("listen error");
- // 创建epoll描述符
- int epoll_fd = epoll_create(MAX_FDS);
- if(epoll_fd == -1) log_error("epoll_create error");
- pthread_t th[THREAD_NUMBER];
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_mutex_init(&fd_mutex, NULL);
- for(int i = 0; i < THREAD_NUMBER; ++i)
- pthread_create(&th[i], &attr, (void*(*)(void*))read_write, &epoll_fd);
- do_accept(&epoll_fd);
- return 0;
- }
- inline void log_error(char *c){
- cout<<c<<": "<<strerror(errno)<<endl;
- _exit(-1);
- }
- void do_accept(int *epoll_fd){
- int rc = 0;
- int connect_fd = 0;
- struct epoll_event ev;
- while(1){
- // pthread_mutex_lock(&fd_mutex);
- connect_fd = accept(sock_fd, NULL, NULL);
- // pthread_mutex_unlock(&fd_mutex);
- if(connect_fd > 0){
- rc = fcntl(connect_fd, F_SETFL, O_NONBLOCK);
- if(rc == -1){log_error("fcntl set nonblock error");}
- ev.data.fd = connect_fd;
- ev.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLERR | EPOLLHUP | EPOLLPRI;
- rc = epoll_ctl(*epoll_fd, EPOLL_CTL_ADD, connect_fd, &ev);
- if(rc == -1) { log_error("epoll_ctl add socket fd error");}
- }
- }
- }
- int read_write(int *epoll_fd){
- int count = 0;
- struct epoll_event ev, events[MAX_FDS];
- char r_buffer[4096];
- 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";
- #define data_fd (events[i].data.fd)
- while(1){
- count = epoll_wait(*epoll_fd, events, MAX_FDS, 1000);
- for(int i = 0; i < count; ++i){
- if(events[i].events&EPOLLIN){
- read(data_fd, r_buffer, sizeof(r_buffer));
- ev.data.fd = data_fd;
- ev.events = EPOLLET | EPOLLOUT;
- epoll_ctl(*epoll_fd, EPOLL_CTL_MOD, data_fd, &ev);
- }
- else if(events[i].events&EPOLLOUT){
- write(data_fd, w_buffer, sizeof(w_buffer));
- ev.data.fd = data_fd;
- epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, data_fd, &ev);
- close(data_fd);
- }
- else{
- ev.data.fd = data_fd;
- epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, data_fd, &ev);
- close(data_fd);
- }
- }
- }
- return 0;
- }
复制代码 |
|