[or-cvs] Track bandwidth usage to estimate capacity
Nick Mathewson
nickm at seul.org
Tue Jul 20 20:57:48 UTC 2004
Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv7201/src/or
Modified Files:
or.h rephist.c
Log Message:
Track bandwidth usage to estimate capacity
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.386
retrieving revision 1.387
diff -u -d -r1.386 -r1.387
--- or.h 20 Jul 2004 20:09:59 -0000 1.386
+++ or.h 20 Jul 2004 20:57:46 -0000 1.387
@@ -1256,6 +1256,9 @@
const char *to_name);
void rep_hist_note_extend_failed(const char *from_name, const char *to_name);
void rep_hist_dump_stats(time_t now, int severity);
+void rep_hist_note_bytes_read(int num_bytes, time_t when);
+void rep_hist_note_bytes_written(int num_bytes, time_t when);
+int rep_hist_bandwidth_assess(time_t when);
/********************************* rendclient.c ***************************/
Index: rephist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rephist.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- rephist.c 16 Jul 2004 22:23:18 -0000 1.14
+++ rephist.c 20 Jul 2004 20:57:46 -0000 1.15
@@ -9,6 +9,8 @@
#include "or.h"
+static void bw_arrays_init(void);
+
/** History of an OR-\>OR link. */
typedef struct link_history_t {
/** When did we start tracking this list? */
@@ -105,6 +107,7 @@
void rep_hist_init(void)
{
history_map = strmap_new();
+ bw_arrays_init();
}
/** Remember that an attempt to connect to the OR with identity digest
@@ -308,6 +311,102 @@
#define NUM_SECS_ROLLING_MEASURE 10
#define NUM_SECS_BW_SUM_IS_VALID (12*60*60) /* half a day */
+#define NUM_SECS_BW_SUM_INTERVAL (15*60)
+#define NUM_TOTALS (NUM_SECS_BW_SUM_IS_VALID/NUM_SECS_BW_SUM_INTERVAL)
+
+/**
+ * Struture to track bandwidth use, and remember the maxima for a given
+ * time period.
+ */
+typedef struct bw_array_t {
+ /** Observation array: Total number of bytes transferred in each of the last
+ * NUM_SECS_ROLLING_MEASURE seconds. This is used as a circular array. */
+ int obs[NUM_SECS_ROLLING_MEASURE];
+ int cur_obs_idx; /**< Current position in obs. */
+ time_t cur_obs_time; /**< Time represented in obs[cur_obs_idx] */
+ int total_obs; /**< Total for all members of obs except obs[cur_obs_idx] */
+ int max_total; /**< Largest value that total_obs has taken on in the current
+ * period. */
+
+ /** When does the next period begin? */
+ time_t next_period;
+ /** Where in 'maxima' should the maximum bandwidth usage for the current
+ * period be stored? */
+ int next_max_idx;
+ /** Circular array of the maximum bandwidth usage for the last NUM_TOTALS
+ * periods */
+ int maxima[NUM_TOTALS];
+} bw_array_t;
+
+/** Shift the current period of b foreward by one.
+ */
+static void commit_max(bw_array_t *b) {
+ /* Store maximum from current period. */
+ b->maxima[b->next_max_idx++] = b->max_total;
+ /* Advance next_period and next_max_idx */
+ b->next_period += NUM_SECS_BW_SUM_INTERVAL;
+ if (b->next_max_idx == NUM_TOTALS)
+ b->next_max_idx = 0;
+ /* Reset max_total. */
+ b->max_total = 0;
+}
+
+/** Shift the current observation time of 'b' foreward by one second.
+ */
+static INLINE void advance_obs(bw_array_t *b) {
+ int nextidx;
+ int total;
+
+ /* Calculate the total bandwidth for the last NUM_SECS_ROLLING_MEASURE
+ * seconds; adjust max_total as needed.*/
+ total = b->total_obs + b->obs[b->cur_obs_idx];
+ if (total > b->max_total)
+ b->max_total = total;
+
+ nextidx = b->cur_obs_idx+1;
+ if (nextidx == NUM_SECS_ROLLING_MEASURE)
+ nextidx = 0;
+
+ b->total_obs = total - b->obs[nextidx];
+ b->obs[nextidx]=0;
+ b->cur_obs_idx = nextidx;
+
+ if (++b->cur_obs_time >= b->next_period)
+ commit_max(b);
+}
+
+/** Add 'n' bytes to the number of bytes in b for second 'when'.
+ */
+static INLINE void add_obs(bw_array_t *b, time_t when, int n) {
+ /* If we're currently adding observations for an earlier second than 'when',
+ * advance 'when' by an appropriate number of seconds. */
+ while (when<b->cur_obs_time)
+ advance_obs(b);
+ b->obs[b->cur_obs_idx] += n;
+}
+
+/** Allocate, initialize, and return a new bw_array.
+ */
+static bw_array_t *bw_array_new(void) {
+ bw_array_t *b;
+ time_t start;
+ b = tor_malloc_zero(sizeof(bw_array_t));
+ start = time(NULL);
+ b->cur_obs_time = start;
+ b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
+ return b;
+}
+
+static bw_array_t *read_array = NULL;
+static bw_array_t *write_array = NULL;
+
+/** Set up read_array and write_array
+ */
+static void bw_arrays_init(void)
+{
+ read_array = bw_array_new();
+ write_array = bw_array_new();
+}
/** We read <b>num_bytes</b> more bytes in second <b>when</b>.
*
@@ -325,7 +424,7 @@
* seen over when-1 to when-1-NUM_SECS_ROLLING_MEASURE, and stick it
* somewhere. See rep_hist_bandwidth_assess() below.
*/
-
+ add_obs(write_array, when, num_bytes);
}
/** We wrote <b>num_bytes</b> more bytes in second <b>when</b>.
@@ -333,6 +432,23 @@
*/
void rep_hist_note_bytes_read(int num_bytes, time_t when) {
/* if we're smart, we can make this func and the one above share code */
+
+ add_obs(read_array, when, num_bytes);
+}
+
+/** Helper: Return the largest value in b->maxima. (This is equal to the
+ * most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last
+ * NUM_SECS_BW_SUM_IS_VALID seconds.)
+ */
+static int find_largest_max(bw_array_t *b)
+{
+ int i,max;
+ max=0;
+ for (i=0; i<NUM_TOTALS; ++i) {
+ if (b->maxima[i]>max)
+ max = b->maxima[i];
+ }
+ return max;
}
/**
@@ -343,13 +459,13 @@
* Return the smaller of these sums, divided by NUM_SECS_ROLLING_MEASURE.
*/
int rep_hist_bandwidth_assess(time_t when) {
-/* To get a handle on space complexity, I promise I will call this
- * function at most every options.DirFetchPostPeriod seconds. So in
- * rep_hist_note_bytes_foo() above, you could keep a running max sum
- * for the current period, and when the period ends you can tuck its max away
- * in a circular array of more managable size. We lose a bit of precision,
- * but this is all guesswork anyway.
- */
+ int w,r;
+ r = find_largest_max(read_array);
+ w = find_largest_max(write_array);
+ if (r>w)
+ return w/(double)NUM_SECS_ROLLING_MEASURE;
+ else
+ return r/(double)NUM_SECS_ROLLING_MEASURE;
return 0;
}
More information about the tor-commits
mailing list