commit df031d7bf33f68948b2c915d681b08ca59c1da37 Author: Mike Perry <mikeperry-...@torproject.org> Date: Tue Nov 3 16:28:52 2020 -0600
Update path-spec.txt for CBT estimator fixes for #40168. Also clarify and improve wording of the timeout calculation section. --- path-spec.txt | 202 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 85 deletions(-) diff --git a/path-spec.txt b/path-spec.txt index 483e37d..c16ef50 100644 --- a/path-spec.txt +++ b/path-spec.txt @@ -361,112 +361,147 @@ of their choices. 2.4. Learning when to give up ("timeout") on circuit construction - Since version 0.2.2.8-alpha, Tor attempts to learn when to give up on - circuits based on network conditions. + Since version 0.2.2.8-alpha, Tor clients attempt to learn when to give + up on circuits based on network conditions. -2.4.1. Distribution choice and parameter estimation +2.4.1. Distribution choice Based on studies of build times, we found that the distribution of - circuit build times appears to be a Frechet distribution. However, - estimators and quantile functions of the Frechet distribution are - difficult to work with and slow to converge. So instead, since we - are only interested in the accuracy of the tail, we approximate - the tail of the distribution with a Pareto curve. + circuit build times appears to be a Frechet distribution (and a multi-modal + Frechet distribution, if more than one guard or bridge is used). However, + estimators and quantile functions of the Frechet distribution are difficult + to work with and slow to converge. So instead, since we are only interested + in the accuracy of the tail, clients approximate the tail of the multi-modal + distribution with a single Pareto curve. - We calculate the parameters for a Pareto distribution fitting the data - using the estimators in equation 4 from: - http://portal.acm.org/citation.cfm?id=1647962.1648139 +2.4.2. How much data to record + + From our observations, the minimum number of circuit build times for a + reasonable fit appears to be on the order of 100. However, to keep a + good fit over the long term, clients store 1000 most recent circuit build + times in a circular array. - This is: + The Tor client should build test circuits at a rate of one every 'cbttestfreq' + (10 seconds) until 'cbtmincircs' (100 circuits) are built, with a maximum of + 'cbtmaxopencircs' (default: 10) circuits open at once. This allows a fresh + Tor to have a CircuitBuildTimeout estimated within 30 minutes after install + or network change (see section 2.4.5 below). - alpha_m = s/(ln(U(X)/Xm^n)) + Timeouts are stored on disk in a histogram of 10ms bin width, the same + width used to calculate the Xm value above. This histogram must be shuffled + after being read from disk, to preserve a proper expiration of old values + after restart. - where s is the total number of completed circuits we have seen, and + Thus, some build time resolution is lost during restart. Implementations may + choose a different persistence mechanism than this histogram, but be aware + that build time binning is still needed for parameter estimation. - U(X) = x_max^u * Prod_s{x_i} +2.4.3. Parameter estimation - with x_i as our i-th completed circuit time, x_max as the longest - completed circuit build time we have yet observed, u as the - number of unobserved timeouts that have no exact value recorded, - and n as u+s, the total number of circuits that either timeout or - complete. + Once 'cbtmincircs' build times are recorded, Tor clients update the + distribution parameters and recompute the timeout every circuit completion + (though see section 2.4.5 for when to pause and reset timeout due to + network change or connectivity loss). - Using log laws, we compute this as the sum of logs to avoid - overflow and ln(1.0+epsilon) precision issues: + Tor clients calculate the parameters for a Pareto distribution fitting the + data using the maximum likelihood estimator. For derivation, see: + https://en.wikipedia.org/wiki/Pareto_distribution#Estimation_of_parameters - alpha_m = s/(u*ln(x_max) + Sum_s{ln(x_i)} - n*ln(Xm)) + Because build times are not a true Pareto distribution, we alter how Xm is + computed. In a max likelihood estimator, the mode of the distribution is + used directly as Xm. - This estimator is closely related to the parameters present in: - http://en.wikipedia.org/wiki/Pareto_distribution#Parameter_estimation - except they are adjusted to handle the fact that our samples are - right-censored at the timeout cutoff. + Instead of using the mode of discrete build times directly, Tor clients + compute the Xm parameter using the weighted average of the the midpoints + of the 'cbtnummodes' (10) most frequently occurring 10ms histogram bins. + (The use of 10 modes was found to minimize error from the selected + cbtquantile, with 10ms bins for quantiles 60-80, compared to many other + heuristics). - Additionally, because this is not a true Pareto distribution, we alter - how Xm is computed. The Xm parameter is computed as the midpoint of the most - frequently occurring 50ms histogram bin, until the point where 1000 - circuits are recorded. After this point, the weighted average of the top - 'cbtnummodes' (default: 3) midpoint modes is used as Xm. All times below - this value are counted as having the midpoint value of this weighted average - bin. + To avoid ln(1.0+epsilon) precision issues, use log laws to rewrite the + estimator for 'alpha' as the sum of logs followed by subtraction, rather + than multiplication and division: + + alpha = n/(Sum_n{ln(MAX(Xm, x_i))} - n*ln(Xm)) + + In this, n is the total number of build times that have completed, x_i is + the ith recorded build time, and Xm is the modes of x_i as above. + + All times below Xm are counted as having the Xm value via the MAX(), + because in Pareto estimators, Xm is supposed to be the lowest value. + However, since clients use mode averaging to estimatre Xm, there can be + values below our Xm. Effectively, the Pareto estimator then treats that + everything smaller than Xm happened at Xm. One can also see that if + clients did not do this, alpha could underflow to become negative, which + results in an exponential curve, not a Pareto probability distribution. The timeout itself is calculated by using the Pareto Quantile function (the inverted CDF) to give us the value on the CDF such that 80% of the mass - of the distribution is below the timeout value. + of the distribution is below the timeout value (parameter 'cbtquantile'). - Thus, we expect that the Tor client will accept the fastest 80% of - the total number of paths on the network. + The Pareto Quantile Function (inverse CDF) is: -2.4.2. How much data to record + F(q) = Xm/((1.0-q)^(1.0/alpha)) - From our observations, the minimum number of circuit build times for a - reasonable fit appears to be on the order of 100. However, to keep a - good fit over the long term, we store 1000 most recent circuit build times - in a circular array. + Thus, clients obtain their circuit build timeout by computing: - The Tor client should build test circuits at a rate of one per - minute up until 100 circuits are built. This allows a fresh Tor to have - a CircuitBuildTimeout estimated within 1.5 hours after install, - upgrade, or network change (see below). + timeout_ms = F(0.8) # 'cbtquantile' == 0.8 - Timeouts are stored on disk in a histogram of 50ms bin width, the same - width used to calculate the Xm value above. This histogram must be shuffled - after being read from disk, to preserve a proper expiration of old values - after restart. + With this, we expect that the Tor client will accept the fastest 80% of the + total number of paths on the network. + + Clients obtain the circuit close time to completely abandon circuits as: + + close_ms = F(0.99) # 'cbtclosequantile' == 0.99 + + To avoid waiting an unreasonably long period of time for circuits that + simply have relays that are down, Tor clients cap timeout_ms at the max + build time actually observed so far, and cap close_ms at twice this max, + but at least 60 seconds: -2.4.3. How to record timeouts + timeout_ms = MIN(timeout_ms, max_observed_timeout) + close_ms = MAX(MIN(close_ms, 2*max_observed_timeout), 'cbtinitialtimeout') - Circuits that pass the timeout threshold should be allowed to continue - building until a time corresponding to the point 'cbtclosequantile' - (default 95) on the Pareto curve, or 60 seconds, whichever is greater. +2.4.4. How to record timeouts - The actual completion times for these circuits should be recorded. - Implementations should completely abandon a circuit and record a value - as an 'unknown' timeout if the total build time exceeds this threshold. + Pareto estimators begin to lose their accuracy if the tail is omitted. + Hence, Tor clients actually calculate two timeouts: a usage timeout, and a + close timeout. - The reason for this is that right-censored pareto estimators begin to lose - their accuracy if more than approximately 5% of the values are censored. - Since we wish to set the cutoff at 20%, we must allow circuits to continue - building past this cutoff point up to the 95th percentile. + Circuits that pass the usage timeout are marked as measurement circuits, + and are allowed to continue to build until the close timeout corresponding + to the point 'cbtclosequantile' (default 99) on the Pareto curve, or 60 + seconds, whichever is greater. -2.4.4. Detecting Changing Network Conditions + The actual completion times for these measurements circuits should be + recorded. - We attempt to detect both network connectivity loss and drastic + Implementations should completely abandon a circuit and ignore the circuit + if the total build time exceeds the close threshold. Such closed circuits + should be ignored, as this typically means one of the relays in the path is + offline. + +2.4.5. Detecting Changing Network Conditions + + Tor clients attempt to detect both network connectivity loss and drastic changes in the timeout characteristics. - We assume that we've had network connectivity loss if a circuit - times out and we've received no cells or TLS handshakes since that - circuit began. We then temporarily stop counting timeouts until - network activity resumes. + Clients assume that they have had network connectivity loss if a circuit + times out and have received no cells or TLS handshakes since that + circuit began. Clients then temporarily stop counting timeouts until + network activity resumes (ie: until a TLS handshake completes or a cell + arrives at the client). - To detect changing network conditions, we keep a history of - the timeout or non-timeout status of the past 20 circuits that - successfully completed at least one hop. If more than 90% of - these circuits timeout, we discard all buildtimes history, reset - the timeout to 60, and then begin recomputing the timeout. + To detect changing network conditions, clients keep a history of + the timeout or non-timeout status of the past 'cbtrecentcount' circuits + (20 circuits) that successfully completed at least one hop. If more than + 90% of these circuits timeout, the client discards all buildtimes history, + resets the timeout to 'cbtinitialtimeout' (60 seconds), and then begins + recomputing the timeout. - If the timeout was already 60 or higher, we double the timeout. + If the timeout was already 60 or higher, the client doubles the timeout. -2.4.5. Consensus parameters governing behavior +2.4.6. Consensus parameters governing behavior Clients that implement circuit build timeout learning should obey the following consensus parameters that govern behavior, in order to allow @@ -483,14 +518,13 @@ of their choices. emergency situations only. cbtnummodes - Default: 3 + Default: 10 Min: 1 Max: 20 Effect: This value governs how many modes to use in the weighted - average calculation of Pareto parameter Xm. A value of 3 introduces - some bias (2-5% of CDF) under ideal conditions, but allows for better - performance in the event that a client chooses guard nodes of radically - different performance characteristics. + average calculation of Pareto parameter Xm. Selecting Xm as the + average of multiple modes improves accuracy of the Pareto tail + for quantile cutoffs from 60-80% (see cbtquantile). cbtrecentcount Default: 20 @@ -522,7 +556,7 @@ of their choices. timeout value. It is a percent (10-99). cbtclosequantile - Default: 95 + Default: 99 Min: Value of cbtquantile parameter Max: 99 Effect: This is the position on the quantile curve to use to set the @@ -530,7 +564,7 @@ of their choices. percent (0-99). cbttestfreq - Default: 60 + Default: 10 Min: 1 Max: 2147483647 (INT32_MAX) Effect: Describes how often in seconds to build a test circuit to @@ -538,12 +572,10 @@ of their choices. have been recorded. cbtmintimeout - Default: 2000 - Min: 500 + Default: 10 + Min: 10 Max: 2147483647 (INT32_MAX) Effect: This is the minimum allowed timeout value in milliseconds. - The minimum is to prevent rounding to 0 (we only check once - per second). cbtinitialtimeout Default: 60000 _______________________________________________ tor-commits mailing list tor-commits@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits