From: Philippe Waroquiers Date: Thu, 29 Sep 2016 20:04:43 +0000 (+0000) Subject: Add an optional 2nd arg to leak-autofreepool to test performance X-Git-Tag: svn/VALGRIND_3_13_0~380 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b53d2291e895c97ea537966832e116d3d36b10f8;p=thirdparty%2Fvalgrind.git Add an optional 2nd arg to leak-autofreepool to test performance e.g. using the beloz for f in 1 2 3 4 5 6 7 8 9; do echo $f; time ./vg-in-place -q ./memcheck/tests/leak-autofreepool 2 $(expr $f \* 100000); done This shows that freeing a mempool with significant nr of elements has a bad effect on performance Note that no effort has been spent to avoid leaks in this optional perf test. This is just to analyse the time taken to free the pool. The above loop shows that a medium size pool (e.g. < 1000000 elts) can already take significant time, probably due to the quadratic algorithm to clear the pool. Note that the increase can vary a lot, probably depending on the way the blocks are spread in the hash table: when lucky, the quadratic algorithm probably somewhat becomes more linear if the elements are 'properly' ordered in the hash table by deletion order. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15986 --- diff --git a/memcheck/tests/leak-autofreepool.c b/memcheck/tests/leak-autofreepool.c index 2bee601819..44da9ebe5c 100644 --- a/memcheck/tests/leak-autofreepool.c +++ b/memcheck/tests/leak-autofreepool.c @@ -1,4 +1,4 @@ - +#include #include #include #include @@ -182,7 +182,7 @@ int main( int argc, char** argv ) int arg; size_t i; - assert(argc == 2); + assert(argc == 2 || argc == 3); assert(argv[1]); assert(strlen(argv[1]) == 1); assert(argv[1][0] >= '0' && argv[1][0] <= '9'); @@ -222,5 +222,62 @@ int main( int argc, char** argv ) // Cleanup. VALGRIND_DESTROY_MEMPOOL(PlainPool); + // Perf test + if (argc == 3) { + struct pool perf_plain_pool; + void *perf_plain_block; + struct pool perf_meta_pool; + void *perf_meta_block; + size_t pool_block_size; + int n; + int nr_elts = atoi( argv[2] ); + time_t dnow; +#define tprintf(...) (dnow = time(NULL), \ + printf(__VA_ARGS__), \ + printf(" %s", ctime(&dnow))) + + pool_block_size = nr_elts * sizeof(struct cell) + sizeof(uint8_t) + 1; + + // Create perf meta pool + VALGRIND_CREATE_META_MEMPOOL + (&perf_meta_pool, 0, 0, + VALGRIND_MEMPOOL_AUTO_FREE | VALGRIND_MEMPOOL_METAPOOL); + perf_meta_block = malloc(pool_block_size); + + VALGRIND_MEMPOOL_ALLOC(&perf_meta_pool, perf_meta_block, + pool_block_size); + + perf_meta_pool.buf = (uint8_t *) perf_meta_block; + perf_meta_pool.allocated = pool_block_size; + perf_meta_pool.used = 0; + + + perf_meta_pool.buf += sizeof(uint8_t); + perf_meta_pool.used += sizeof(uint8_t); + + // Create perf plain pool + VALGRIND_CREATE_MEMPOOL(&perf_plain_pool, 0, 0); + perf_plain_block = malloc(pool_block_size); + + perf_plain_pool.buf = (uint8_t *) perf_plain_block; + perf_plain_pool.allocated = pool_block_size;; + perf_plain_pool.used = 0; + + perf_plain_pool.buf += sizeof(uint8_t); + perf_plain_pool.used += sizeof(uint8_t); + + tprintf("allocating %d elts", nr_elts); + for (n = 0; n < nr_elts; n++) { + (void) allocate_meta_style (&perf_meta_pool, sizeof(struct cell)); + (void) allocate_plain_style (&perf_plain_pool, sizeof(struct cell)); + } + + tprintf("freeing mempool"); + VALGRIND_MEMPOOL_FREE(&perf_meta_pool, perf_meta_block); + tprintf("destroying mempool"); + VALGRIND_DESTROY_MEMPOOL(&perf_meta_pool); + tprintf("done"); + + } return 0; }