]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add an optional 2nd arg to leak-autofreepool to test performance
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 29 Sep 2016 20:04:43 +0000 (20:04 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 29 Sep 2016 20:04:43 +0000 (20:04 +0000)
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

memcheck/tests/leak-autofreepool.c

index 2bee601819183eca9f7144a517e575281448095e..44da9ebe5c1f94f1e1943ab12d01d2c89fb5a4e7 100644 (file)
@@ -1,4 +1,4 @@
-
+#include <time.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <assert.h>
@@ -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;
 }