]> granicus.if.org Git - libevent/commitdiff
cache clock_gettime/gettimeofday values in base
authorNiels Provos <provos@gmail.com>
Sat, 3 May 2008 18:23:44 +0000 (18:23 +0000)
committerNiels Provos <provos@gmail.com>
Sat, 3 May 2008 18:23:44 +0000 (18:23 +0000)
svn:r758

ChangeLog
event-internal.h
event.c
test/bench_cascade.c

index d6cb1f12b56eb18ac07bf618710bed58b29796c8..8122ac15efd506ecdbbd661d14e70b2eb4bd63db 100644 (file)
--- 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.
index f1372b232e341522c9614f2d4a0a65cb34762734..e80171ee8659a9b626b25d4a8cf4906ed87fa86e 100644 (file)
@@ -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 7f387d3392dbf01df5ceb03bb75c3720305289c1..0215deaeaf867bf99c039ddffacfb9c04e87ea0c 100644 (file)
--- 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);
index 809b9993c0ebb219e42b1c4b2cbe57baf4f90d25..69508e1e91abdcf59762f15a77c19e308b476dc3 100644 (file)
@@ -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);