diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-05-24 17:12:57 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-05-24 17:12:57 +0000 |
commit | d3d86b17a761011f62dc2e06c04c0af8f1a75ef6 (patch) | |
tree | efb329c2d77ef6f39c02db8db62bfa18ad5f4d6d | |
parent | d0a5c4f9848f44c46f001428bd3078673033ef19 (diff) | |
download | tor-d3d86b17a761011f62dc2e06c04c0af8f1a75ef6.tar.gz tor-d3d86b17a761011f62dc2e06c04c0af8f1a75ef6.zip |
r12916@catbus: nickm | 2007-05-24 12:43:45 -0400
Add math functions to round values to the nearest power of 2. Make mempools more careful about making sure that the size of their chunks is a little less than a power of 2, not a little more.
svn:r10304
-rw-r--r-- | doc/TODO | 1 | ||||
-rw-r--r-- | src/common/compat.h | 2 | ||||
-rw-r--r-- | src/common/mempool.c | 14 | ||||
-rw-r--r-- | src/common/util.c | 48 | ||||
-rw-r--r-- | src/common/util.h | 4 | ||||
-rw-r--r-- | src/or/test.c | 20 |
6 files changed, 85 insertions, 4 deletions
@@ -83,6 +83,7 @@ Things we'd like to do in 0.2.0.x: - Push/pull documents as appropriate. o Have clients know which authorities are v3 authorities, and what their keys are. + - While we're at it, let v3 authorities have fqdns lines. - Start caching consensus documents once authorities make them - Start downloading and using consensus documents once caches serve them . 104: Long and Short Router Descriptors (by Jun 1) diff --git a/src/common/compat.h b/src/common/compat.h index 085af036d1..cd36437407 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -96,6 +96,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #if defined(__GNUC__) && __GNUC__ >= 3 #define ATTR_NORETURN __attribute__((noreturn)) #define ATTR_PURE __attribute__((pure)) +#define ATTR_CONST __attribute__((const)) #define ATTR_MALLOC __attribute__((malloc)) #define ATTR_NORETURN __attribute__((noreturn)) #define ATTR_NONNULL(x) __attribute__((nonnull x)) @@ -108,6 +109,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #else #define ATTR_NORETURN #define ATTR_PURE +#define ATTR_CONST #define ATTR_MALLOC #define ATTR_NORETURN #define ATTR_NONNULL(x) diff --git a/src/common/mempool.c b/src/common/mempool.c index 2b1775c1ba..665a803af2 100644 --- a/src/common/mempool.c +++ b/src/common/mempool.c @@ -361,18 +361,24 @@ mp_pool_new(size_t item_size, size_t chunk_capacity) /* Now we figure out how many items fit in each chunk. We need to fit at * least 2 items per chunk. No chunk can be more than MAX_CHUNK bytes long, * or less than MIN_CHUNK. */ - /* XXXX020 Try a bit harder here: we want to be a bit less than a power of - 2, not a bit over. */ if (chunk_capacity > MAX_CHUNK) chunk_capacity = MAX_CHUNK; - if (chunk_capacity < alloc_size * 2 + CHUNK_OVERHEAD) - chunk_capacity = alloc_size * 2 + CHUNK_OVERHEAD; + /* Try to be around a power of 2 in size, since that's what allocators like + * handing out. 512K-1 byte is a lot better than 512K+1 byte. */ + chunk_capacity = (size_t) round_to_power_of_2(chunk_capacity); + while (chunk_capacity < alloc_size * 2 + CHUNK_OVERHEAD) + chunk_capacity *= 2; if (chunk_capacity < MIN_CHUNK) chunk_capacity = MIN_CHUNK; pool->new_chunk_capacity = (chunk_capacity-CHUNK_OVERHEAD) / alloc_size; pool->item_alloc_size = alloc_size; + log_debug(LD_MM, "Capacity is %lu, item size is %lu, alloc size is %lu", + (unsigned long)pool->new_chunk_capacity, + (unsigned long)pool->item_alloc_size, + (unsigned long)(pool->new_chunk_capacity*pool->item_alloc_size)); + return pool; } diff --git a/src/common/util.c b/src/common/util.c index d4a30a1459..7ca08363d0 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -214,6 +214,54 @@ _tor_free(void *mem) } /* ===== + * Math + * ===== */ + +/** Returns floor(log2(u64)). If u64 is 0, (incorrectly) returns 0. */ +int +tor_log2(uint64_t u64) +{ + int r = 0; + if (u64 >= (U64_LITERAL(1)<<32)) { + u64 >>= 32; + r = 32; + } + if (u64 >= (U64_LITERAL(1)<<16)) { + u64 >>= 16; + r += 16; + } + if (u64 >= (U64_LITERAL(1)<<8)) { + u64 >>= 8; + r += 8; + } + if (u64 >= (U64_LITERAL(1)<<4)) { + u64 >>= 4; + r += 4; + } + if (u64 >= (U64_LITERAL(1)<<2)) { + u64 >>= 2; + r += 2; + } + if (u64 >= (U64_LITERAL(1)<<1)) { + u64 >>= 1; + r += 1; + } + return r; +} + +/** Return the power of 2 closest to <b>u64</b>. */ +uint64_t +round_to_power_of_2(uint64_t u64) +{ + int lg2 = tor_log2(u64); + uint64_t low = U64_LITERAL(1) << lg2, high = U64_LITERAL(1) << (lg2+1); + if (high - u64 < u64 - low) + return high; + else + return low; +} + +/* ===== * String manipulation * ===== */ diff --git a/src/common/util.h b/src/common/util.h index 6b32708c5e..f04160935d 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -142,6 +142,10 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, /** Macro: true if two values have different boolean values. */ #define bool_neq(a,b) (!(a)!=!(b)) +/* Math functions */ +int tor_log2(uint64_t u64) ATTR_CONST; +uint64_t round_to_power_of_2(uint64_t u64); + /* String manipulation */ /** Allowable characters in a hexadecimal string. */ diff --git a/src/or/test.c b/src/or/test.c index ca6ffa0db7..4307b1007e 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -946,6 +946,26 @@ test_util(void) tor_gettimeofday(&end); /* We might've timewarped a little. */ test_assert(tv_udiff(&start, &end) >= -5000); + + /* Test tor_log2(). */ + test_eq(tor_log2(64), 6); + test_eq(tor_log2(65), 6); + test_eq(tor_log2(63), 5); + test_eq(tor_log2(1), 0); + test_eq(tor_log2(2), 1); + test_eq(tor_log2(3), 1); + test_eq(tor_log2(4), 2); + test_eq(tor_log2(5), 2); + test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55); + test_eq(tor_log2(UINT64_MAX), 63); + + /* Test round_to_power_of_2 */ + test_eq(round_to_power_of_2(120), 128); + test_eq(round_to_power_of_2(128), 128); + test_eq(round_to_power_of_2(130), 128); + test_eq(round_to_power_of_2(U64_LITERAL(40000000000000000)), + U64_LITERAL(1)<<55); + test_eq(round_to_power_of_2(0), 2); } static void |