from trunk: cache clock_gettime/gettimeofday values in base

svn:r759
This commit is contained in:
Niels Provos 2008-05-03 18:27:24 +00:00
parent 2a69a5ea9a
commit bfdf56c22e
3 changed files with 32 additions and 17 deletions

View File

@ -7,6 +7,7 @@ Changes in 1.4.4-stable:
o fix a bug in bufferevent read water marks and add a test for them o fix a bug in bufferevent read water marks and add a test for them
o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents
o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy. o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy.
o reduce system calls for getting current time by caching it.
Changes in 1.4.3-stable: Changes in 1.4.3-stable:

View File

@ -66,6 +66,8 @@ struct event_base {
struct timeval event_tv; struct timeval event_tv;
struct min_heap timeheap; struct min_heap timeheap;
struct timeval tv_cache;
}; };
/* Internal use only: Functions that might be missing from <sys/queue.h> */ /* Internal use only: Functions that might be missing from <sys/queue.h> */

46
event.c
View File

@ -137,8 +137,13 @@ detect_monotonic(void)
} }
static int static int
gettime(struct timeval *tp) gettime(struct event_base *base, struct timeval *tp)
{ {
if (base->tv_cache.tv_sec) {
*tp = base->tv_cache;
return (0);
}
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec ts; struct timespec ts;
@ -179,7 +184,7 @@ event_base_new(void)
event_gotsig = 0; event_gotsig = 0;
detect_monotonic(); detect_monotonic();
gettime(&base->event_tv); gettime(base, &base->event_tv);
min_heap_ctor(&base->timeheap); min_heap_ctor(&base->timeheap);
TAILQ_INIT(&base->eventqueue); TAILQ_INIT(&base->eventqueue);
@ -497,10 +502,17 @@ event_base_loop(struct event_base *base, int flags)
return (1); return (1);
} }
/* update last old time */
gettime(base, &base->event_tv);
/* clear time cache */
base->tv_cache.tv_sec = 0;
res = evsel->dispatch(base, evbase, tv_p); res = evsel->dispatch(base, evbase, tv_p);
if (res == -1) if (res == -1)
return (-1); return (-1);
gettime(base, &base->tv_cache);
timeout_process(base); timeout_process(base);
@ -668,7 +680,7 @@ event_pending(struct event *ev, short event, struct timeval *tv)
/* See if there is a timeout that we should report */ /* See if there is a timeout that we should report */
if (tv != NULL && (flags & event & EV_TIMEOUT)) { if (tv != NULL && (flags & event & EV_TIMEOUT)) {
gettime(&now); gettime(ev->ev_base, &now);
evutil_timersub(&ev->ev_timeout, &now, &res); evutil_timersub(&ev->ev_timeout, &now, &res);
/* correctly remap to real time */ /* correctly remap to real time */
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
@ -720,7 +732,7 @@ event_add(struct event *ev, struct timeval *tv)
event_queue_remove(base, ev, EVLIST_ACTIVE); event_queue_remove(base, ev, EVLIST_ACTIVE);
} }
gettime(&now); gettime(base, &now);
evutil_timeradd(&now, tv, &ev->ev_timeout); evutil_timeradd(&now, tv, &ev->ev_timeout);
event_debug(( event_debug((
@ -820,7 +832,7 @@ timeout_next(struct event_base *base, struct timeval **tv_p)
return (0); return (0);
} }
if (gettime(&now) == -1) if (gettime(base, &now) == -1)
return (-1); return (-1);
if (evutil_timercmp(&ev->ev_timeout, &now, <=)) { if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
@ -854,7 +866,7 @@ timeout_correct(struct event_base *base, struct timeval *tv)
return; return;
/* Check if time is running backwards */ /* Check if time is running backwards */
gettime(tv); gettime(base, tv);
if (evutil_timercmp(tv, &base->event_tv, >=)) { if (evutil_timercmp(tv, &base->event_tv, >=)) {
base->event_tv = *tv; base->event_tv = *tv;
return; return;
@ -885,7 +897,7 @@ timeout_process(struct event_base *base)
if (min_heap_empty(&base->timeheap)) if (min_heap_empty(&base->timeheap))
return; return;
gettime(&now); gettime(base, &now);
while ((ev = min_heap_top(&base->timeheap))) { while ((ev = min_heap_top(&base->timeheap))) {
if (evutil_timercmp(&ev->ev_timeout, &now, >)) if (evutil_timercmp(&ev->ev_timeout, &now, >))
@ -912,19 +924,19 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
ev->ev_flags &= ~queue; ev->ev_flags &= ~queue;
switch (queue) { switch (queue) {
case EVLIST_INSERTED:
TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
break;
case EVLIST_ACTIVE: case EVLIST_ACTIVE:
base->event_count_active--; base->event_count_active--;
TAILQ_REMOVE(base->activequeues[ev->ev_pri], TAILQ_REMOVE(base->activequeues[ev->ev_pri],
ev, ev_active_next); ev, ev_active_next);
break; break;
case EVLIST_SIGNAL:
TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT: case EVLIST_TIMEOUT:
min_heap_erase(&base->timeheap, ev); min_heap_erase(&base->timeheap, ev);
break; break;
case EVLIST_INSERTED: case EVLIST_SIGNAL:
TAILQ_REMOVE(&base->eventqueue, ev, ev_next); TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break; break;
default: default:
event_errx(1, "%s: unknown queue %x", __func__, queue); event_errx(1, "%s: unknown queue %x", __func__, queue);
@ -948,20 +960,20 @@ event_queue_insert(struct event_base *base, struct event *ev, int queue)
ev->ev_flags |= queue; ev->ev_flags |= queue;
switch (queue) { switch (queue) {
case EVLIST_INSERTED:
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
break;
case EVLIST_ACTIVE: case EVLIST_ACTIVE:
base->event_count_active++; base->event_count_active++;
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri], TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
ev,ev_active_next); ev,ev_active_next);
break; break;
case EVLIST_SIGNAL:
TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break;
case EVLIST_TIMEOUT: { case EVLIST_TIMEOUT: {
min_heap_push(&base->timeheap, ev); min_heap_push(&base->timeheap, ev);
break; break;
} }
case EVLIST_INSERTED: case EVLIST_SIGNAL:
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next); TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break; break;
default: default:
event_errx(1, "%s: unknown queue %x", __func__, queue); event_errx(1, "%s: unknown queue %x", __func__, queue);