diff options
author | Karsten Loesing <karsten.loesing@gmx.net> | 2009-07-05 19:53:25 +0200 |
---|---|---|
committer | Karsten Loesing <karsten.loesing@gmx.net> | 2009-07-05 19:53:25 +0200 |
commit | b493a2ccb97e00f4fe3acb5c59c941c2babaeebb (patch) | |
tree | eec79d7610ffc84657bfed515cfd948970377e39 /src/or/rephist.c | |
parent | 4d6af73db88e409764f43fc6cdaa432d667becf3 (diff) | |
download | tor-b493a2ccb97e00f4fe3acb5c59c941c2babaeebb.tar.gz tor-b493a2ccb97e00f4fe3acb5c59c941c2babaeebb.zip |
If configured, write cell statistics to disk periodically.
Diffstat (limited to 'src/or/rephist.c')
-rw-r--r-- | src/or/rephist.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/or/rephist.c b/src/or/rephist.c index f1f502cad2..a7f525e542 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -2576,3 +2576,174 @@ hs_usage_write_statistics_to_file(time_t now) tor_free(fname); } +/*** cell statistics ***/ + +#ifdef ENABLE_BUFFER_STATS +/** Start of the current buffer stats interval. */ +time_t start_of_buffer_stats_interval; + +typedef struct circ_buffer_stats_t { + uint32_t processed_cells; + double mean_num_cells_in_queue; + double mean_time_cells_in_queue; + uint32_t local_circ_id; +} circ_buffer_stats_t; + +/** Holds stats. */ +smartlist_t *circuits_for_buffer_stats = NULL; + +/** Remember cell statistics for circuit <b>circ</b> at time + * <b>end_of_interval</b> and reset cell counters in case the circuit + * remains open in the next measurement interval. */ +void +add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval) +{ + circ_buffer_stats_t *stat; + time_t start_of_interval; + int interval_length; + or_circuit_t *orcirc; + if (CIRCUIT_IS_ORIGIN(circ)) + return; + orcirc = TO_OR_CIRCUIT(circ); + if (!orcirc->processed_cells) + return; + if (!circuits_for_buffer_stats) + circuits_for_buffer_stats = smartlist_create(); + start_of_interval = circ->timestamp_created > + start_of_buffer_stats_interval ? + circ->timestamp_created : + start_of_buffer_stats_interval; + interval_length = (int) (end_of_interval - start_of_interval); + stat = tor_malloc_zero(sizeof(circ_buffer_stats_t)); + stat->processed_cells = orcirc->processed_cells; + /* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */ + stat->mean_num_cells_in_queue = interval_length == 0 ? 0.0 : + (double) orcirc->total_cell_waiting_time / + (double) interval_length / 1000.0 / 2.0; + stat->mean_time_cells_in_queue = + (double) orcirc->total_cell_waiting_time / + (double) orcirc->processed_cells; + smartlist_add(circuits_for_buffer_stats, stat); + orcirc->total_cell_waiting_time = 0; + orcirc->processed_cells = 0; +} + +/** Sorting helper: return -1, 1, or 0 based on comparison of two + * circ_buffer_stats_t */ +static int +_buffer_stats_compare_entries(const void **_a, const void **_b) +{ + const circ_buffer_stats_t *a = *_a, *b = *_b; + if (a->processed_cells < b->processed_cells) + return 1; + else if (a->processed_cells > b->processed_cells) + return -1; + else + return 0; +} + +/** Append buffer statistics to local file. */ +void +dump_buffer_stats(void) +{ + time_t now = time(NULL); + char *filename; + char written[ISO_TIME_LEN+1]; + open_file_t *open_file = NULL; + FILE *out; +#define SHARES 10 + int processed_cells[SHARES], circs_in_share[SHARES], + number_of_circuits, i; + double queued_cells[SHARES], time_in_queue[SHARES]; + smartlist_t *str_build = smartlist_create(); + char *str = NULL; + char buf[32]; + circuit_t *circ; + /* add current circuits to stats */ + for (circ = _circuit_get_global_list(); circ; circ = circ->next) + add_circ_to_buffer_stats(circ, now); + /* calculate deciles */ + memset(processed_cells, 0, SHARES * sizeof(int)); + memset(circs_in_share, 0, SHARES * sizeof(int)); + memset(queued_cells, 0, SHARES * sizeof(double)); + memset(time_in_queue, 0, SHARES * sizeof(double)); + smartlist_sort(circuits_for_buffer_stats, + _buffer_stats_compare_entries); + number_of_circuits = smartlist_len(circuits_for_buffer_stats); + i = 0; + SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats, + circ_buffer_stats_t *, stat) + { + int share = i++ * SHARES / number_of_circuits; + processed_cells[share] += stat->processed_cells; + queued_cells[share] += stat->mean_num_cells_in_queue; + time_in_queue[share] += stat->mean_time_cells_in_queue; + circs_in_share[share]++; + } + SMARTLIST_FOREACH_END(stat); + /* clear buffer stats history */ + SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, + stat, tor_free(stat)); + smartlist_clear(circuits_for_buffer_stats); + /* write to file */ + filename = get_datadir_fname("buffer-stats"); + out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND, + 0600, &open_file); + if (!out) + goto done; + format_iso_time(written, now); + if (fprintf(out, "written %s (%d s)\n", written, + DUMP_BUFFER_STATS_INTERVAL) < 0) + goto done; + for (i = 0; i < SHARES; i++) { + tor_snprintf(buf, sizeof(buf), "%d", !circs_in_share[i] ? 0 : + processed_cells[i] / circs_in_share[i]); + smartlist_add(str_build, tor_strdup(buf)); + } + str = smartlist_join_strings(str_build, ",", 0, NULL); + if (fprintf(out, "processed-cells %s\n", str) < 0) + goto done; + tor_free(str); + SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); + smartlist_clear(str_build); + for (i = 0; i < SHARES; i++) { + tor_snprintf(buf, sizeof(buf), "%.2f", circs_in_share[i] == 0 ? 0.0 : + queued_cells[i] / (double) circs_in_share[i]); + smartlist_add(str_build, tor_strdup(buf)); + } + str = smartlist_join_strings(str_build, ",", 0, NULL); + if (fprintf(out, "queued-cells %s\n", str) < 0) + goto done; + tor_free(str); + SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); + smartlist_clear(str_build); + for (i = 0; i < SHARES; i++) { + tor_snprintf(buf, sizeof(buf), "%.0f", circs_in_share[i] == 0 ? 0.0 : + time_in_queue[i] / (double) circs_in_share[i]); + smartlist_add(str_build, tor_strdup(buf)); + } + str = smartlist_join_strings(str_build, ",", 0, NULL); + if (fprintf(out, "time-in-queue %s\n", str) < 0) + goto done; + tor_free(str); + SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); + smartlist_free(str_build); + str_build = NULL; + if (fprintf(out, "number-of-circuits-per-share %d\n", + (number_of_circuits + SHARES - 1) / SHARES) < 0) + goto done; + finish_writing_to_file(open_file); + open_file = NULL; + done: + if (open_file) + abort_writing_to_file(open_file); + tor_free(filename); + if (str_build) { + SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); + smartlist_free(str_build); + } + tor_free(str); +#undef SHARES +} +#endif + |