소스 검색

Teach to use epoll(7) on httperf(1).

master^2
junsik.park 5 년 전
부모
커밋
c8f1bd43ea
3개의 변경된 파일148개의 추가작업 그리고 4개의 파일을 삭제
  1. +5
    -0
      configure.ac
  2. +3
    -0
      src/conn.h
  3. +140
    -4
      src/core.c

+ 5
- 0
configure.ac 파일 보기

@@ -93,4 +93,9 @@ if test "$enable_debug" = yes; then
CFLAGS="${CFLAGS} -DDEBUG"
fi

AC_ARG_WITH(epoll, AS_HELP_STRING([--with-epoll], [use epoll if available]))
AS_IF([test "$with_epoll" != "no"],
AC_CHECK_FUNC(epoll_create,
AC_DEFINE([HAVE_EPOLL], 1, [#undef HAVE_EPOLL])))

AC_OUTPUT(Makefile man/Makefile src/stat/Makefile src/lib/Makefile src/gen/Makefile src/Makefile)

+ 3
- 0
src/conn.h 파일 보기

@@ -108,6 +108,9 @@ typedef struct Conn

#ifdef HAVE_SSL
SSL *ssl; /* SSL connection info */
#endif
#ifdef HAVE_EPOLL
int epoll_added; /* is fd added into epoll? */
#endif
}
Conn;


+ 140
- 4
src/core.c 파일 보기

@@ -51,6 +51,10 @@
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
#endif

#ifdef HAVE_KEVENT
#include <sys/event.h>

@@ -107,10 +111,17 @@ static u_long max_burst_len;
#ifdef HAVE_KEVENT
static int kq, max_sd = 0;
#else
#ifdef HAVE_EPOLL
#define EPOLL_N_MAX 8192
static int epoll_fd, max_sd = 0;
static struct epoll_event *epoll_events;
static int epoll_timeout;
#else
static fd_set rdfds, wrfds;
static int min_sd = 0x7fffffff, max_sd = 0, alloced_sd_to_conn = 0;
static struct timeval select_timeout;
#endif
#endif
static struct sockaddr_in myaddr;
static struct address_pool myaddrs;
#ifndef HAVE_KEVENT
@@ -151,12 +162,14 @@ static char http11req_nohost[] =
enum Syscalls {
SC_BIND, SC_CONNECT, SC_READ, SC_SELECT, SC_SOCKET, SC_WRITEV,
SC_SSL_READ, SC_SSL_WRITEV, SC_KEVENT,
SC_EPOLL_CREATE, SC_EPOLL_CTL, SC_EPOLL_WAIT,
SC_NUM_SYSCALLS
};

static const char *const syscall_name[SC_NUM_SYSCALLS] = {
"bind", "connct", "read", "select", "socket", "writev",
"ssl_read", "ssl_writev", "kevent"
"ssl_read", "ssl_writev", "kevent",
"epoll_create", "epoll_ctl", "epoll_wait"
};
static Time syscall_time[SC_NUM_SYSCALLS];
static u_int syscall_count[SC_NUM_SYSCALLS];
@@ -373,6 +386,23 @@ clear_active(Conn * s, enum IO_DIR dir)
"write" : "read");
exit(1);
}
#else
#ifdef HAVE_EPOLL
struct epoll_event ev;
int error;

if (dir == WRITE)
ev.events = EPOLLIN;
else
ev.events = EPOLLOUT;
ev.data.ptr = s;

error = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sd, &ev);
if (error < 0) {
error = errno;
fprintf(stderr, "failed to EPOLL_CTL_DEL\n");
exit(1);
}
#else
fd_set * fdset;
@@ -381,6 +411,7 @@ clear_active(Conn * s, enum IO_DIR dir)
else
fdset = &rdfds;
FD_CLR(sd, fdset);
#endif
#endif
if (dir == WRITE)
s->writing = 0;
@@ -404,6 +435,28 @@ set_active(Conn * s, enum IO_DIR dir)
"write" : "read");
exit(1);
}
#else
#ifdef HAVE_EPOLL
struct epoll_event ev;
int error;

if (dir == WRITE)
ev.events = EPOLLOUT;
else
ev.events = EPOLLIN;
ev.data.ptr = s;

if (s->epoll_added)
error = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sd, &ev);
else {
error = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sd, &ev);
s->epoll_added = 1;
}
if (error < 0) {
error = errno;
fprintf(stderr, "failed to EPOLL_CTL_MOD\n");
exit(1);
}
#else
fd_set * fdset;
@@ -414,6 +467,7 @@ set_active(Conn * s, enum IO_DIR dir)
FD_SET(sd, fdset);
if (sd < min_sd)
min_sd = sd;
#endif
#endif
if (sd >= max_sd)
max_sd = sd;
@@ -882,7 +936,7 @@ core_init(void)
Any_Type arg;

memset(&hash_table, 0, sizeof(hash_table));
#ifndef HAVE_KEVENT
#if !defined(HAVE_KEVENT) && !defined(HAVE_EPOLL)
memset(&rdfds, 0, sizeof(rdfds));
memset(&wrfds, 0, sizeof(wrfds));
#endif
@@ -922,6 +976,23 @@ core_init(void)
strerror(errno));
}
#else
#ifdef HAVE_EPOLL
epoll_fd = epoll_create(EPOLL_N_MAX);
if (epoll_fd < 0) {
fprintf(stderr,
"%s: failed to create epoll: %s", prog_name,
strerror(errno));
exit(1);
}
epoll_events = calloc(EPOLL_N_MAX, sizeof(struct epoll_event));
if (epoll_events == NULL) {
fprintf(stderr,
"%s: failed to create epoll_events: %s", prog_name,
strerror(errno));
exit(1);
}
epoll_timeout = 0;
#else
#ifdef DONT_POLL
/*
* This causes select() to take several milliseconds on both Linux/x86
@@ -939,6 +1010,7 @@ core_init(void)
select_timeout.tv_sec = 0;
select_timeout.tv_usec = 0;
#endif
#endif
#endif

/*
@@ -1120,7 +1192,7 @@ core_connect(Conn * s)
}

s->sd = sd;
#ifndef HAVE_KEVENT
#if !defined(HAVE_KEVENT) && !defined(HAVE_EPOLL)
if (sd >= alloced_sd_to_conn) {
size_t size, old_size;

@@ -1368,8 +1440,19 @@ core_close(Conn * conn)
#endif

if (sd >= 0) {
#ifdef HAVE_EPOLL
struct epoll_event ev = { 0, { 0 } };
int error;

error = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sd, &ev);
if (error < 0) {
error = errno;
printf("EPOLL_CTL_DEL: %d %d %d\n", epoll_fd, sd, error);
assert(error == 0);
}
#endif
close(sd);
#ifndef HAVE_KEVENT
#if !defined(HAVE_KEVENT) && !defined(HAVE_EPOLL)
sd_to_conn[sd] = 0;
FD_CLR(sd, &wrfds);
FD_CLR(sd, &rdfds);
@@ -1445,6 +1528,58 @@ core_loop(void)
}
}
#else
#ifdef HAVE_EPOLL
void
core_loop(void)
{
struct epoll_event *ep;
int i, n;
Any_Type arg;
Conn *conn;

while (running) {
++iteration;

timer_tick();
n = epoll_wait(epoll_fd, epoll_events, EPOLL_N_MAX, epoll_timeout);
if (n < 0 && errno == EINTR) {
fprintf(stderr, "failed to fetch event: %s",
strerror(errno));
continue;
}
ep = epoll_events;
for (i = 0; i < n; i++, ep++) {
conn = ep->data.ptr;
conn_inc_ref(conn);

if (conn->watchdog) {
timer_cancel(conn->watchdog);
conn->watchdog = 0;
}
if (conn->state == S_CONNECTING) {
#ifdef HAVE_SSL
if (param.use_ssl)
core_ssl_connect(conn);
else
#endif
if (ep->events & EPOLLOUT) {
clear_active(conn, WRITE);
conn->state = S_CONNECTED;
arg.l = 0;
event_signal(EV_CONN_CONNECTED, (Object*)conn, arg);
}
} else {
if (ep->events & (EPOLLIN | EPOLLHUP) && conn->recvq)
do_recv(conn);
if (ep->events & EPOLLOUT && conn->sendq)
do_send(conn);
}
conn_dec_ref(conn);
}
}
close(epoll_fd);
}
#else
void
core_loop(void)
{
@@ -1541,6 +1676,7 @@ core_loop(void)
}
}
#endif
#endif

void
core_exit(void)


불러오는 중...
취소
저장