From 7fbc0184334da7325d983d187ee14fdc0326123a Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Tue, 25 Oct 2011 14:11:13 +0200 Subject: [PATCH 1/2] Add percentiles to the desc stats reporting To get a better idea what's going on on Tonga, add some code to report how often the most and least frequently fetched descriptor was fetched, as well as 25, 50, 75 percentile. Also ensure we only count bridge descriptors here. --- changes/ticket4294 | 8 ++++++++ src/or/dirserv.c | 13 ++++++++++++- src/or/rephist.c | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 changes/ticket4294 diff --git a/changes/ticket4294 b/changes/ticket4294 new file mode 100644 index 0000000000..5041495542 --- /dev/null +++ b/changes/ticket4294 @@ -0,0 +1,8 @@ +(NOTE: THIS SHOULD REPLACE THE TICKET 4200 ENTRY IN THE CHANGELOG) + o Minor features: + - The Bridge Authority now writes statistics on how many bridge + descriptors it gave out in total, and how many unique descriptors it + gave out. It also lists how often the most and least commonly fetched + descriptors were given out, as well as the median and 25/75 percentile. + Implements tickets 4200 and 4294. + diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 4b9587b0fc..5cb4aba5aa 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -3488,6 +3488,8 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST); time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH; + const or_options_t *options = get_options(); + while (smartlist_len(conn->fingerprint_stack) && connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) { const char *body; @@ -3509,7 +3511,16 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) * unknown bridge descriptor has shown up between then and now. */ continue; } - rep_hist_note_desc_served(sd->identity_digest); + + /** If we are the bridge authority and the descriptor is a bridge + * descriptor, remember that we served this descriptor for desc stats. */ + if (options->BridgeAuthoritativeDir && by_fp) { + const routerinfo_t *router = + router_get_by_id_digest(sd->identity_digest); + tor_assert(router); + if (router->purpose == ROUTER_PURPOSE_BRIDGE) + rep_hist_note_desc_served(sd->identity_digest); + } body = signed_descriptor_get_body(sd); if (conn->zlib_state) { /* XXXX022 This 'last' business should actually happen on the last diff --git a/src/or/rephist.c b/src/or/rephist.c index f8ebe644fc..359e4886a3 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -2643,7 +2643,7 @@ rep_hist_reset_desc_stats(time_t now) void rep_hist_desc_stats_term(void) { - digestmap_free(served_descs, NULL); + digestmap_free(served_descs, _tor_free); served_descs = NULL; start_of_served_descs_stats_interval = 0; total_descriptor_downloads = 0; @@ -2659,18 +2659,43 @@ rep_hist_format_desc_stats(time_t now) char t[ISO_TIME_LEN+1]; char *result; + digestmap_iter_t *iter; + const char *key; + void *val; + unsigned size; + int *vals; + int n = 0, *count; + if (!start_of_served_descs_stats_interval) return NULL; + size = digestmap_size(served_descs); + vals = tor_malloc(size * sizeof(int)); + + for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); + iter = digestmap_iter_next(served_descs, iter) ) { + digestmap_iter_get(iter, &key, &val); + count = val; + vals[n++] = *count; + (void)key; + } + format_iso_time(t, now); tor_asprintf(&result, - "served-descs-stats-end %s (%d s) total=%lu unique=%u\n", + "served-descs-stats-end %s (%d s) total=%lu unique=%u " + "max=%d q3=%d md=%d q1=%d min=%d\n", t, (unsigned) (now - start_of_served_descs_stats_interval), total_descriptor_downloads, - digestmap_size(served_descs)); + size, + find_nth_int(vals, size, size-1), + find_nth_int(vals, size, (3*size-1)/4), + find_nth_int(vals, size, (size-1)/2), + find_nth_int(vals, size, (size-1)/4), + find_nth_int(vals, size, 0)); + tor_free(vals); return result; } @@ -2712,9 +2737,17 @@ rep_hist_desc_stats_write(time_t now) void rep_hist_note_desc_served(const char * desc) { + int *val; if (!served_descs) return; // We're not collecting stats - digestmap_set(served_descs, desc, (void *)1); + val = digestmap_get(served_descs, desc); + if (!val) { + val = tor_malloc(sizeof(int)); + *val = 1; + digestmap_set(served_descs, desc, val); + } else { + (*val)++; + } total_descriptor_downloads++; } From 7ab0b5ff713aa609cbbd3c2152b34a7ef60d3e2a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 25 Oct 2011 15:32:26 -0400 Subject: [PATCH 2/2] Avoid likely memory fragmentation from rep_hist_note_descs_served When you're doing malloc(sizeof(int)), something may well have gone wrong. This technique is a bit abusive, but we're already relying on it working correctly in geoip.c. --- src/or/rephist.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/or/rephist.c b/src/or/rephist.c index 359e4886a3..6bbb93b821 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -2643,7 +2643,7 @@ rep_hist_reset_desc_stats(time_t now) void rep_hist_desc_stats_term(void) { - digestmap_free(served_descs, _tor_free); + digestmap_free(served_descs, NULL); served_descs = NULL; start_of_served_descs_stats_interval = 0; total_descriptor_downloads = 0; @@ -2664,7 +2664,7 @@ rep_hist_format_desc_stats(time_t now) void *val; unsigned size; int *vals; - int n = 0, *count; + int n = 0; if (!start_of_served_descs_stats_interval) return NULL; @@ -2674,10 +2674,11 @@ rep_hist_format_desc_stats(time_t now) for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); iter = digestmap_iter_next(served_descs, iter) ) { + uintptr_t count; digestmap_iter_get(iter, &key, &val); - count = val; - vals[n++] = *count; - (void)key; + count = (uintptr_t)val; + vals[n++] = (int)count; + (void)key; } format_iso_time(t, now); @@ -2737,17 +2738,15 @@ rep_hist_desc_stats_write(time_t now) void rep_hist_note_desc_served(const char * desc) { - int *val; + void *val; + uintptr_t count; if (!served_descs) return; // We're not collecting stats val = digestmap_get(served_descs, desc); - if (!val) { - val = tor_malloc(sizeof(int)); - *val = 1; - digestmap_set(served_descs, desc, val); - } else { - (*val)++; - } + count = (uintptr_t)val; + if (count != INT_MAX) + ++count; + digestmap_set(served_descs, desc, (void*)count); total_descriptor_downloads++; }