Loading ChangeLog +10 −0 Original line number Diff line number Diff line Changes in version 0.2.2.7-alpha - 2009-??-?? o Major features: - When choosing which cells to relay first, we can now favor circuits that have been quiet recently, so as to get lower latency for low-volume circuits. By default, relays enable or disable this feature based on a setting in the consensus. Preliminary testing suggests that this should make the network feel faster as more relays use it. You can override this default by using the new "CircuitPriorityHalflife" config option. Design and code by Ian Goldberg, Can Tang, and Chris Alexander. o Minor features: - New config option "CircuitStreamTimeout" to override our internal timeout schedule for how many seconds until we detach a stream from Loading doc/tor.1.in +13 −0 Original line number Diff line number Diff line Loading @@ -424,6 +424,19 @@ ORPort. (Default: 1) \fBPreferTunneledDirConns \fR\fB0\fR|\fB1\fP If non-zero, we will avoid directory servers that don't support tunneled directory connections, when possible. (Default: 1) .LP .TP \fBCircuitPriorityHalflife \fR\fBNUM\fB1\fP If this value is set, we override the default algorithm for choosing which circuit's cells to deliver or relay first. When the value is 0, we round-robin between the active circuits on a connection, delivering one cell from each in turn. When the value is positive, we prefer delivering cells from whichever connection has the lowest weighted cell count, where cells are weighted exponentially according to the supplied CircuitPrioirityHalflife value (in seconds). If this option is not set at all, we use the behavior recommended in the current consensus networkstatus. This is an advanced option; you generally shouldn't have mess with it. (Default: not set.) .SH CLIENT OPTIONS .PP Loading src/common/container.c +91 −9 Original line number Diff line number Diff line Loading @@ -605,6 +605,38 @@ smartlist_uniq_strings(smartlist_t *sl) /* Heap-based priority queue implementation for O(lg N) insert and remove. * Recall that the heap property is that, for every index I, h[I] < * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]]. * * For us to remove items other than the topmost item, each item must store * its own index within the heap. When calling the pqueue functions, tell * them about the offset of the field that stores the index within the item. * * Example: * * typedef struct timer_t { * struct timeval tv; * int heap_index; * } timer_t; * * static int compare(const void *p1, const void *p2) { * const timer_t *t1 = p1, *t2 = p2; * if (t1->tv.tv_sec < t2->tv.tv_sec) { * return -1; * } else if (t1->tv.tv_sec > t2->tv.tv_sec) { * return 1; * } else { * return t1->tv.tv_usec - t2->tv_usec; * } * } * * void timer_heap_insert(smartlist_t *heap, timer_t *timer) { * smartlist_pqueue_add(heap, compare, STRUCT_OFFSET(timer_t, heap_index), * timer); * } * * void timer_heap_pop(smartlist_t *heap) { * return smartlist_pqueue_pop(heap, compare, * STRUCT_OFFSET(timer_t, heap_index)); * } */ /* For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x] Loading @@ -616,12 +648,22 @@ smartlist_uniq_strings(smartlist_t *sl) #define RIGHT_CHILD(i) ( 2*(i) + 2 ) #define PARENT(i) ( ((i)-1) / 2 ) #define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset)) #define UPDATE_IDX(i) do { \ void *updated = sl->list[i]; \ *IDXP(updated) = i; \ } while (0) #define IDX_OF_ITEM(p) (*IDXP(p)) /** Helper. <b>sl</b> may have at most one violation of the heap property: * the item at <b>idx</b> may be greater than one or both of its children. * Restore the heap property. */ static INLINE void smartlist_heapify(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, int idx) { while (1) { Loading @@ -644,21 +686,28 @@ smartlist_heapify(smartlist_t *sl, void *tmp = sl->list[idx]; sl->list[idx] = sl->list[best_idx]; sl->list[best_idx] = tmp; UPDATE_IDX(idx); UPDATE_IDX(best_idx); idx = best_idx; } } } /** Insert <b>item</b> into the heap stored in <b>sl</b>, where order * is determined by <b>compare</b>. */ /** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is * determined by <b>compare</b> and the offset of the item in the heap is * stored in an int-typed field at position <b>idx_field_offset</b> within * item. */ void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item) { int idx; smartlist_add(sl,item); UPDATE_IDX(sl->num_used-1); for (idx = sl->num_used - 1; idx; ) { int parent = PARENT(idx); Loading @@ -666,6 +715,8 @@ smartlist_pqueue_add(smartlist_t *sl, void *tmp = sl->list[parent]; sl->list[parent] = sl->list[idx]; sl->list[idx] = tmp; UPDATE_IDX(parent); UPDATE_IDX(idx); idx = parent; } else { return; Loading @@ -674,32 +725,63 @@ smartlist_pqueue_add(smartlist_t *sl, } /** Remove and return the top-priority item from the heap stored in <b>sl</b>, * where order is determined by <b>compare</b>. <b>sl</b> must not be * empty. */ * where order is determined by <b>compare</b> and the item's position is * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must * not be empty. */ void * smartlist_pqueue_pop(smartlist_t *sl, int (*compare)(const void *a, const void *b)) int (*compare)(const void *a, const void *b), int idx_field_offset) { void *top; tor_assert(sl->num_used); top = sl->list[0]; *IDXP(top)=-1; if (--sl->num_used) { sl->list[0] = sl->list[sl->num_used]; smartlist_heapify(sl, compare, 0); UPDATE_IDX(0); smartlist_heapify(sl, compare, idx_field_offset, 0); } return top; } /** Remove the item <b>item</b> from the heap stored in <b>sl</b>, * where order is determined by <b>compare</b> and the item's position is * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must * not be empty. */ void smartlist_pqueue_remove(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item) { int idx = IDX_OF_ITEM(item); tor_assert(idx >= 0); tor_assert(sl->list[idx] == item); --sl->num_used; *IDXP(item) = -1; if (idx == sl->num_used) { return; } else { sl->list[idx] = sl->list[sl->num_used]; UPDATE_IDX(idx); smartlist_heapify(sl, compare, idx_field_offset, idx); } } /** Assert that the heap property is correctly maintained by the heap stored * in <b>sl</b>, where order is determined by <b>compare</b>. */ void smartlist_pqueue_assert_ok(smartlist_t *sl, int (*compare)(const void *a, const void *b)) int (*compare)(const void *a, const void *b), int idx_field_offset) { int i; for (i = sl->num_used - 1; i > 0; --i) { for (i = sl->num_used - 1; i >= 0; --i) { if (i>0) tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0); tor_assert(IDX_OF_ITEM(sl->list[i]) == i); } } Loading src/common/container.h +9 −2 Original line number Diff line number Diff line Loading @@ -118,11 +118,18 @@ int smartlist_bsearch_idx(const smartlist_t *sl, const void *key, void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item); void *smartlist_pqueue_pop(smartlist_t *sl, int (*compare)(const void *a, const void *b)); int (*compare)(const void *a, const void *b), int idx_field_offset); void smartlist_pqueue_remove(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item); void smartlist_pqueue_assert_ok(smartlist_t *sl, int (*compare)(const void *a, const void *b)); int (*compare)(const void *a, const void *b), int idx_field_offset); #define SPLIT_SKIP_SPACE 0x01 #define SPLIT_IGNORE_BLANK 0x02 Loading src/or/circuitlist.c +16 −0 Original line number Diff line number Diff line Loading @@ -385,6 +385,12 @@ init_circuit_base(circuit_t *circ) circ->package_window = circuit_initial_package_window(); circ->deliver_window = CIRCWINDOW_START; /* Initialize the cell_ewma_t structure */ circ->n_cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); circ->n_cell_ewma.cell_count = 0.0; circ->n_cell_ewma.heap_index = -1; circ->n_cell_ewma.is_for_p_conn = 0; circuit_add(circ); } Loading Loading @@ -432,6 +438,16 @@ or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn) init_circuit_base(TO_CIRCUIT(circ)); /* Initialize the cell_ewma_t structure */ /* Initialize the cell counts to 0 */ circ->p_cell_ewma.cell_count = 0.0; circ->p_cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); circ->p_cell_ewma.is_for_p_conn = 1; /* It's not in any heap yet. */ circ->p_cell_ewma.heap_index = -1; return circ; } Loading Loading
ChangeLog +10 −0 Original line number Diff line number Diff line Changes in version 0.2.2.7-alpha - 2009-??-?? o Major features: - When choosing which cells to relay first, we can now favor circuits that have been quiet recently, so as to get lower latency for low-volume circuits. By default, relays enable or disable this feature based on a setting in the consensus. Preliminary testing suggests that this should make the network feel faster as more relays use it. You can override this default by using the new "CircuitPriorityHalflife" config option. Design and code by Ian Goldberg, Can Tang, and Chris Alexander. o Minor features: - New config option "CircuitStreamTimeout" to override our internal timeout schedule for how many seconds until we detach a stream from Loading
doc/tor.1.in +13 −0 Original line number Diff line number Diff line Loading @@ -424,6 +424,19 @@ ORPort. (Default: 1) \fBPreferTunneledDirConns \fR\fB0\fR|\fB1\fP If non-zero, we will avoid directory servers that don't support tunneled directory connections, when possible. (Default: 1) .LP .TP \fBCircuitPriorityHalflife \fR\fBNUM\fB1\fP If this value is set, we override the default algorithm for choosing which circuit's cells to deliver or relay first. When the value is 0, we round-robin between the active circuits on a connection, delivering one cell from each in turn. When the value is positive, we prefer delivering cells from whichever connection has the lowest weighted cell count, where cells are weighted exponentially according to the supplied CircuitPrioirityHalflife value (in seconds). If this option is not set at all, we use the behavior recommended in the current consensus networkstatus. This is an advanced option; you generally shouldn't have mess with it. (Default: not set.) .SH CLIENT OPTIONS .PP Loading
src/common/container.c +91 −9 Original line number Diff line number Diff line Loading @@ -605,6 +605,38 @@ smartlist_uniq_strings(smartlist_t *sl) /* Heap-based priority queue implementation for O(lg N) insert and remove. * Recall that the heap property is that, for every index I, h[I] < * H[LEFT_CHILD[I]] and h[I] < H[RIGHT_CHILD[I]]. * * For us to remove items other than the topmost item, each item must store * its own index within the heap. When calling the pqueue functions, tell * them about the offset of the field that stores the index within the item. * * Example: * * typedef struct timer_t { * struct timeval tv; * int heap_index; * } timer_t; * * static int compare(const void *p1, const void *p2) { * const timer_t *t1 = p1, *t2 = p2; * if (t1->tv.tv_sec < t2->tv.tv_sec) { * return -1; * } else if (t1->tv.tv_sec > t2->tv.tv_sec) { * return 1; * } else { * return t1->tv.tv_usec - t2->tv_usec; * } * } * * void timer_heap_insert(smartlist_t *heap, timer_t *timer) { * smartlist_pqueue_add(heap, compare, STRUCT_OFFSET(timer_t, heap_index), * timer); * } * * void timer_heap_pop(smartlist_t *heap) { * return smartlist_pqueue_pop(heap, compare, * STRUCT_OFFSET(timer_t, heap_index)); * } */ /* For a 1-indexed array, we would use LEFT_CHILD[x] = 2*x and RIGHT_CHILD[x] Loading @@ -616,12 +648,22 @@ smartlist_uniq_strings(smartlist_t *sl) #define RIGHT_CHILD(i) ( 2*(i) + 2 ) #define PARENT(i) ( ((i)-1) / 2 ) #define IDXP(p) ((int*)STRUCT_VAR_P(p, idx_field_offset)) #define UPDATE_IDX(i) do { \ void *updated = sl->list[i]; \ *IDXP(updated) = i; \ } while (0) #define IDX_OF_ITEM(p) (*IDXP(p)) /** Helper. <b>sl</b> may have at most one violation of the heap property: * the item at <b>idx</b> may be greater than one or both of its children. * Restore the heap property. */ static INLINE void smartlist_heapify(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, int idx) { while (1) { Loading @@ -644,21 +686,28 @@ smartlist_heapify(smartlist_t *sl, void *tmp = sl->list[idx]; sl->list[idx] = sl->list[best_idx]; sl->list[best_idx] = tmp; UPDATE_IDX(idx); UPDATE_IDX(best_idx); idx = best_idx; } } } /** Insert <b>item</b> into the heap stored in <b>sl</b>, where order * is determined by <b>compare</b>. */ /** Insert <b>item</b> into the heap stored in <b>sl</b>, where order is * determined by <b>compare</b> and the offset of the item in the heap is * stored in an int-typed field at position <b>idx_field_offset</b> within * item. */ void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item) { int idx; smartlist_add(sl,item); UPDATE_IDX(sl->num_used-1); for (idx = sl->num_used - 1; idx; ) { int parent = PARENT(idx); Loading @@ -666,6 +715,8 @@ smartlist_pqueue_add(smartlist_t *sl, void *tmp = sl->list[parent]; sl->list[parent] = sl->list[idx]; sl->list[idx] = tmp; UPDATE_IDX(parent); UPDATE_IDX(idx); idx = parent; } else { return; Loading @@ -674,32 +725,63 @@ smartlist_pqueue_add(smartlist_t *sl, } /** Remove and return the top-priority item from the heap stored in <b>sl</b>, * where order is determined by <b>compare</b>. <b>sl</b> must not be * empty. */ * where order is determined by <b>compare</b> and the item's position is * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must * not be empty. */ void * smartlist_pqueue_pop(smartlist_t *sl, int (*compare)(const void *a, const void *b)) int (*compare)(const void *a, const void *b), int idx_field_offset) { void *top; tor_assert(sl->num_used); top = sl->list[0]; *IDXP(top)=-1; if (--sl->num_used) { sl->list[0] = sl->list[sl->num_used]; smartlist_heapify(sl, compare, 0); UPDATE_IDX(0); smartlist_heapify(sl, compare, idx_field_offset, 0); } return top; } /** Remove the item <b>item</b> from the heap stored in <b>sl</b>, * where order is determined by <b>compare</b> and the item's position is * stored at position <b>idx_field_offset</b> within the item. <b>sl</b> must * not be empty. */ void smartlist_pqueue_remove(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item) { int idx = IDX_OF_ITEM(item); tor_assert(idx >= 0); tor_assert(sl->list[idx] == item); --sl->num_used; *IDXP(item) = -1; if (idx == sl->num_used) { return; } else { sl->list[idx] = sl->list[sl->num_used]; UPDATE_IDX(idx); smartlist_heapify(sl, compare, idx_field_offset, idx); } } /** Assert that the heap property is correctly maintained by the heap stored * in <b>sl</b>, where order is determined by <b>compare</b>. */ void smartlist_pqueue_assert_ok(smartlist_t *sl, int (*compare)(const void *a, const void *b)) int (*compare)(const void *a, const void *b), int idx_field_offset) { int i; for (i = sl->num_used - 1; i > 0; --i) { for (i = sl->num_used - 1; i >= 0; --i) { if (i>0) tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0); tor_assert(IDX_OF_ITEM(sl->list[i]) == i); } } Loading
src/common/container.h +9 −2 Original line number Diff line number Diff line Loading @@ -118,11 +118,18 @@ int smartlist_bsearch_idx(const smartlist_t *sl, const void *key, void smartlist_pqueue_add(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item); void *smartlist_pqueue_pop(smartlist_t *sl, int (*compare)(const void *a, const void *b)); int (*compare)(const void *a, const void *b), int idx_field_offset); void smartlist_pqueue_remove(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset, void *item); void smartlist_pqueue_assert_ok(smartlist_t *sl, int (*compare)(const void *a, const void *b)); int (*compare)(const void *a, const void *b), int idx_field_offset); #define SPLIT_SKIP_SPACE 0x01 #define SPLIT_IGNORE_BLANK 0x02 Loading
src/or/circuitlist.c +16 −0 Original line number Diff line number Diff line Loading @@ -385,6 +385,12 @@ init_circuit_base(circuit_t *circ) circ->package_window = circuit_initial_package_window(); circ->deliver_window = CIRCWINDOW_START; /* Initialize the cell_ewma_t structure */ circ->n_cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); circ->n_cell_ewma.cell_count = 0.0; circ->n_cell_ewma.heap_index = -1; circ->n_cell_ewma.is_for_p_conn = 0; circuit_add(circ); } Loading Loading @@ -432,6 +438,16 @@ or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn) init_circuit_base(TO_CIRCUIT(circ)); /* Initialize the cell_ewma_t structure */ /* Initialize the cell counts to 0 */ circ->p_cell_ewma.cell_count = 0.0; circ->p_cell_ewma.last_adjusted_tick = cell_ewma_get_tick(); circ->p_cell_ewma.is_for_p_conn = 1; /* It's not in any heap yet. */ circ->p_cell_ewma.heap_index = -1; return circ; } Loading