summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--event-internal.h2
-rw-r--r--event.c46
-rw-r--r--test/bench_cascade.c12
4 files changed, 41 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index d6cb1f12..8122ac15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -85,6 +85,7 @@ Changes in current version:
o switch internal uses of event_set over to use event_assign.
o introduce evbuffer_contiguous_space() api that tells a user how much data is available in the first buffer chain
o introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient.
+ o reduce system calls for getting current time by caching it.
Changes in 1.4.0:
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
diff --git a/event-internal.h b/event-internal.h
index f1372b23..e80171ee 100644
--- a/event-internal.h
+++ b/event-internal.h
@@ -68,6 +68,8 @@ struct event_base {
struct min_heap timeheap;
+ struct timeval tv_cache;
+
/* threading support */
unsigned long th_owner_id;
unsigned long (*th_get_id)(void);
diff --git a/event.c b/event.c
index 7f387d33..0215deae 100644
--- a/event.c
+++ b/event.c
@@ -148,8 +148,13 @@ detect_monotonic(void)
}
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)
struct timespec ts;
@@ -190,7 +195,7 @@ event_base_new(void)
event_gotsig = 0;
detect_monotonic();
- gettime(&base->event_tv);
+ gettime(base, &base->event_tv);
min_heap_ctor(&base->timeheap);
TAILQ_INIT(&base->eventqueue);
@@ -532,10 +537,17 @@ event_base_loop(struct event_base *base, int flags)
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);
if (res == -1)
return (-1);
+ gettime(base, &base->tv_cache);
timeout_process(base);
@@ -736,7 +748,7 @@ event_pending(struct event *ev, short event, struct timeval *tv)
/* See if there is a timeout that we should report */
if (tv != NULL && (flags & event & EV_TIMEOUT)) {
- gettime(&now);
+ gettime(ev->ev_base, &now);
evutil_timersub(&ev->ev_timeout, &now, &res);
/* correctly remap to real time */
gettimeofday(&now, NULL);
@@ -803,7 +815,7 @@ event_add_internal(struct event *ev, struct timeval *tv)
event_queue_remove(base, ev, EVLIST_ACTIVE);
}
- gettime(&now);
+ gettime(base, &now);
evutil_timeradd(&now, tv, &ev->ev_timeout);
event_debug((
@@ -941,7 +953,7 @@ timeout_next(struct event_base *base, struct timeval **tv_p)
goto out;
}
- if (gettime(&now) == -1) {
+ if (gettime(base, &now) == -1) {
res = -1;
goto out;
}
@@ -979,7 +991,7 @@ timeout_correct(struct event_base *base, struct timeval *tv)
return;
/* Check if time is running backwards */
- gettime(tv);
+ gettime(base, tv);
EVTHREAD_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock);
if (evutil_timercmp(tv, &base->event_tv, >=)) {
@@ -1017,7 +1029,7 @@ timeout_process(struct event_base *base)
return;
}
- gettime(&now);
+ gettime(base, &now);
while ((ev = min_heap_top(&base->timeheap))) {
if (evutil_timercmp(&ev->ev_timeout, &now, >))
@@ -1045,19 +1057,19 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
ev->ev_flags &= ~queue;
switch (queue) {
+ case EVLIST_INSERTED:
+ TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
+ break;
case EVLIST_ACTIVE:
base->event_count_active--;
TAILQ_REMOVE(base->activequeues[ev->ev_pri],
ev, ev_active_next);
break;
- case EVLIST_SIGNAL:
- TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
- break;
case EVLIST_TIMEOUT:
min_heap_erase(&base->timeheap, ev);
break;
- case EVLIST_INSERTED:
- TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
+ case EVLIST_SIGNAL:
+ TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
break;
default:
event_errx(1, "%s: unknown queue %x", __func__, queue);
@@ -1081,20 +1093,20 @@ event_queue_insert(struct event_base *base, struct event *ev, int queue)
ev->ev_flags |= queue;
switch (queue) {
+ case EVLIST_INSERTED:
+ TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
+ break;
case EVLIST_ACTIVE:
base->event_count_active++;
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
ev,ev_active_next);
break;
- case EVLIST_SIGNAL:
- TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
- break;
case EVLIST_TIMEOUT: {
min_heap_push(&base->timeheap, ev);
break;
}
- case EVLIST_INSERTED:
- TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
+ case EVLIST_SIGNAL:
+ TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
break;
default:
event_errx(1, "%s: unknown queue %x", __func__, queue);
diff --git a/test/bench_cascade.c b/test/bench_cascade.c
index 809b9993..69508e1e 100644
--- a/test/bench_cascade.c
+++ b/test/bench_cascade.c
@@ -77,7 +77,7 @@ static struct timeval *
run_once(int num_pipes)
{
int *cp, i;
- static struct timeval ts, te;
+ static struct timeval ts, te, tv_timeout;
events = calloc(num_pipes, sizeof(struct event));
pipes = calloc(num_pipes * 2, sizeof(int));
@@ -94,10 +94,17 @@ run_once(int num_pipes)
}
}
+ /* measurements includes event setup */
+ gettimeofday(&ts, NULL);
+
+ /* provide a default timeout for events */
+ timerclear(&tv_timeout);
+ tv_timeout.tv_sec = 60;
+
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
long fd = i < num_pipes - 1 ? cp[3] : -1;
event_set(&events[i], cp[0], EV_READ, read_cb, (void *) fd);
- event_add(&events[i], NULL);
+ event_add(&events[i], &tv_timeout);
}
fired = 0;
@@ -105,7 +112,6 @@ run_once(int num_pipes)
/* kick everything off with a single write */
write(pipes[1], "e", 1);
- gettimeofday(&ts, NULL);
event_dispatch();
gettimeofday(&te, NULL);