[or-cvs] r17690: {tor} Replace calls to time(NULL) that occur on the order of once (in tor/trunk: . doc src/common src/or)

nickm at seul.org nickm at seul.org
Thu Dec 18 17:19:18 UTC 2008


Author: nickm
Date: 2008-12-18 12:19:04 -0500 (Thu, 18 Dec 2008)
New Revision: 17690

Modified:
   tor/trunk/ChangeLog
   tor/trunk/doc/TODO.021
   tor/trunk/src/common/util.c
   tor/trunk/src/common/util.h
   tor/trunk/src/or/connection.c
   tor/trunk/src/or/connection_edge.c
   tor/trunk/src/or/main.c
   tor/trunk/src/or/relay.c
   tor/trunk/src/or/test.c
Log:
Replace calls to time(NULL) that occur on the order of once per read, one per write, or once per cell with calls to a function that looks at a cached value of time.  This is tricksy to benchmark, since it will only help on systems where time() is a syscall and syscalls are relatively slow.

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/ChangeLog	2008-12-18 17:19:04 UTC (rev 17690)
@@ -43,6 +43,9 @@
     - On platforms with a maximum syslog string length, truncate syslog
       messages to that length ourselves, rather than relying on the
       system to do it for us.
+    - Optimize out calls to time(NULL) that occur for every IO operation, or
+      for every cell. On systems where time() is a slow syscalls, this will
+      be slightly helpful.
 
   o Minor features (controller):
     - New CONSENSUS_ARRIVED event to note when a new consensus has

Modified: tor/trunk/doc/TODO.021
===================================================================
--- tor/trunk/doc/TODO.021	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/doc/TODO.021	2008-12-18 17:19:04 UTC (rev 17690)
@@ -362,7 +362,7 @@
       "who can change what" in local_routerstatus explicit.  Make
       local_routerstatus (or equivalent) subsume all places to go for "what
       router is this?"
-    - Don't call time(NULL) so much; instead have a static time_t field
+    o Don't call time(NULL) so much; instead have a static time_t field
       that gets updated only a handful of times per second.
     - Refactor unit tests into multiple files
 

Modified: tor/trunk/src/common/util.c
===================================================================
--- tor/trunk/src/common/util.c	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/common/util.c	2008-12-18 17:19:04 UTC (rev 17690)
@@ -1285,8 +1285,39 @@
 }
 
 /* =====
+ * Cached time
+ * ===== */
+
+#ifndef TIME_IS_FAST
+/** Cached estimate of the currrent time.  Updated around once per second;
+ * may be a few seconds off if we are really busy.  This is a hack to avoid
+ * calling time(NULL) (which not everybody has optimized) on critical paths.
+ */
+static time_t cached_approx_time = 0;
+
+/** Return a cached estimate of the current time from when
+ * update_approx_time() was last called.  This is a hack to avoid calling
+ * time(NULL) on critical paths: please do not even think of calling it
+ * anywhere else. */
+time_t
+approx_time(void)
+{
+  return cached_approx_time;
+}
+
+/** Update the cached estimate of the current time.  This function SHOULD be
+ * called once per second, and MUST be called before the first call to
+ * get_approx_time. */
+void
+update_approx_time(time_t now)
+{
+  cached_approx_time = now;
+}
+#endif
+
+/* =====
  * Fuzzy time
- * XXXX022 Use this consistently or rip it out.
+ * XXXX022 Use this consistently or rip most of it out.
  * ===== */
 
 /* In a perfect world, everybody would run ntp, and ntp would be perfect, so

Modified: tor/trunk/src/common/util.h
===================================================================
--- tor/trunk/src/common/util.h	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/common/util.h	2008-12-18 17:19:04 UTC (rev 17690)
@@ -213,6 +213,16 @@
 int parse_iso_time(const char *buf, time_t *t);
 int parse_http_time(const char *buf, struct tm *tm);
 int format_time_interval(char *out, size_t out_len, long interval);
+
+/* Cached time */
+#ifdef TIME_IS_FAST
+#define approx_time() time(NULL)
+#define update_approx_time(t) STMT_NIL
+#else
+time_t approx_time(void);
+void update_approx_time(time_t now);
+#endif
+
 /* Fuzzy time. */
 void ftime_set_maximum_sloppiness(int seconds);
 void ftime_set_estimated_skew(int seconds);

Modified: tor/trunk/src/or/connection.c
===================================================================
--- tor/trunk/src/or/connection.c	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/or/connection.c	2008-12-18 17:19:04 UTC (rev 17690)
@@ -1724,7 +1724,7 @@
 
   if (global_read_bucket <= 0) {
     reason = "global read bucket exhausted. Pausing.";
-  } else if (connection_counts_as_relayed_traffic(conn, time(NULL)) &&
+  } else if (connection_counts_as_relayed_traffic(conn, approx_time()) &&
              global_relayed_read_bucket <= 0) {
     reason = "global relayed read bucket exhausted. Pausing.";
   } else if (connection_speaks_cells(conn) &&
@@ -1748,7 +1748,7 @@
 
   if (global_write_bucket <= 0) {
     reason = "global write bucket exhausted. Pausing.";
-  } else if (connection_counts_as_relayed_traffic(conn, time(NULL)) &&
+  } else if (connection_counts_as_relayed_traffic(conn, approx_time()) &&
              global_relayed_write_bucket <= 0) {
     reason = "global relayed write bucket exhausted. Pausing.";
 #if 0
@@ -1928,7 +1928,7 @@
   if (conn->marked_for_close)
     return 0; /* do nothing */
 
-  conn->timestamp_lastread = time(NULL);
+  conn->timestamp_lastread = approx_time();
 
   switch (conn->type) {
     case CONN_TYPE_OR_LISTENER:
@@ -1994,7 +1994,7 @@
 
     if (n_read) {
       /* Probably a no-op, but hey. */
-      connection_buckets_decrement(linked, time(NULL), 0, n_read);
+      connection_buckets_decrement(linked, approx_time(), 0, n_read);
 
       if (connection_flushed_some(linked) < 0)
         connection_mark_for_close(linked);
@@ -2034,8 +2034,7 @@
 
   if (at_most == -1) { /* we need to initialize it */
     /* how many bytes are we allowed to read? */
-    /* XXXX021 too many calls to time(). Do they hurt? */
-    at_most = connection_bucket_read_limit(conn, time(NULL));
+    at_most = connection_bucket_read_limit(conn, approx_time());
   }
 
   slack_in_buf = buf_slack(conn->inbuf);
@@ -2155,7 +2154,7 @@
     edge_conn->n_read += (int)n_read;
   }
 
-  connection_buckets_decrement(conn, time(NULL), n_read, n_written);
+  connection_buckets_decrement(conn, approx_time(), n_read, n_written);
 
   if (more_to_read && result == at_most) {
     slack_in_buf = buf_slack(conn->inbuf);
@@ -2223,7 +2222,7 @@
   socklen_t len=(socklen_t)sizeof(e);
   int result;
   ssize_t max_to_write;
-  time_t now = time(NULL);
+  time_t now = approx_time();
   size_t n_read = 0, n_written = 0;
 
   tor_assert(!connection_is_listener(conn));
@@ -2350,7 +2349,7 @@
     edge_conn->n_written += (int)n_written;
   }
 
-  connection_buckets_decrement(conn, time(NULL), n_read, n_written);
+  connection_buckets_decrement(conn, approx_time(), n_read, n_written);
 
   if (result > 0) {
     /* If we wrote any bytes from our buffer, then call the appropriate

Modified: tor/trunk/src/or/connection_edge.c
===================================================================
--- tor/trunk/src/or/connection_edge.c	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/or/connection_edge.c	2008-12-18 17:19:04 UTC (rev 17690)
@@ -2159,7 +2159,7 @@
     uint32_t a;
     size_t len = strlen(ap_conn->socks_request->address);
     char c = 0;
-    /* XXXX021 This logic is a little ugly: we check for an in-addr.arpa ending
+    /* XXXX This logic is a little ugly: we check for an in-addr.arpa ending
      * on the address.  If we have one, the address is already in the right
      * order, so we'll leave it alone later.  Otherwise, we reverse it and
      * turn it into an in-addr.arpa address. */

Modified: tor/trunk/src/or/main.c
===================================================================
--- tor/trunk/src/or/main.c	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/or/main.c	2008-12-18 17:19:04 UTC (rev 17690)
@@ -1192,6 +1192,7 @@
 
   /* log_fn(LOG_NOTICE, "Tick."); */
   tor_gettimeofday(&now);
+  update_approx_time(now.tv_sec);
 
   /* the second has rolled over. check more stuff. */
   bytes_written = stats_prev_global_write_bucket - global_write_bucket;
@@ -1461,6 +1462,8 @@
                       event_active(conn->read_event, EV_READ, 1));
     called_loop_once = smartlist_len(active_linked_connection_lst) ? 1 : 0;
 
+    update_approx_time(time(NULL));
+
     /* poll until we have an event, or the second ends, or until we have
      * some active linked connections to trigger events for. */
     loop_result = event_loop(called_loop_once ? EVLOOP_ONCE : 0);
@@ -2059,6 +2062,7 @@
 tor_main(int argc, char *argv[])
 {
   int result = 0;
+  update_approx_time(time(NULL));
   tor_threads_init();
   init_logging();
 #ifdef USE_DMALLOC

Modified: tor/trunk/src/or/relay.c
===================================================================
--- tor/trunk/src/or/relay.c	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/or/relay.c	2008-12-18 17:19:04 UTC (rev 17690)
@@ -505,8 +505,7 @@
 
   if (cell_direction == CELL_DIRECTION_OUT && circ->n_conn) {
     /* if we're using relaybandwidthrate, this conn wants priority */
-    /* XXXX021 the call to time() seems little too frequent */
-    circ->n_conn->client_used = time(NULL);
+    circ->n_conn->client_used = approx_time();
   }
 
   if (cell_direction == CELL_DIRECTION_OUT) {
@@ -1840,7 +1839,7 @@
      * get called, and we can start putting more data onto the buffer then.
      */
     log_debug(LD_GENERAL, "Primed a buffer.");
-    connection_or_flush_from_first_active_circuit(orconn, 1, time(NULL));
+    connection_or_flush_from_first_active_circuit(orconn, 1, approx_time());
   }
 }
 

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2008-12-18 17:18:14 UTC (rev 17689)
+++ tor/trunk/src/or/test.c	2008-12-18 17:19:04 UTC (rev 17690)
@@ -4538,6 +4538,7 @@
   }
 #endif
 
+  update_approx_time(time(NULL));
   options = options_new();
   tor_threads_init();
   init_logging();



More information about the tor-commits mailing list