diff --git a/.gitignore b/.gitignore index 055a09d..e1dadd0 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,10 @@ /autom4te.cache/ /benchmark/.deps /benchmark/.dirstamp +/binary_trees +/binary_trees.exe +/binary_trees_shared +/binary_trees_shared.exe /compile /config.guess /config.log diff --git a/Makefile.am b/Makefile.am index 70d26c8..05f8a2d 100755 --- a/Makefile.am +++ b/Makefile.am @@ -853,7 +853,8 @@ noinst_LTLIBRARIES += librun_benchmark.la librun_benchmark_la_SOURCES = \ benchmark/run_benchmark.c benchmark/run_benchmark.h -noinst_PROGRAMS += malloc_bench malloc_bench_shared +noinst_PROGRAMS += malloc_bench malloc_bench_shared \ + binary_trees binary_trees_shared malloc_bench_SOURCES = benchmark/malloc_bench.cc malloc_bench_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) @@ -864,6 +865,16 @@ malloc_bench_shared_SOURCES = benchmark/malloc_bench.cc malloc_bench_shared_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) malloc_bench_shared_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) malloc_bench_shared_LDADD = librun_benchmark.la libtcmalloc_minimal.la $(PTHREAD_LIBS) + +binary_trees_SOURCES = benchmark/binary_trees.cc +binary_trees_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) +binary_trees_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) -static +binary_trees_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS) + +binary_trees_shared_SOURCES = benchmark/binary_trees.cc +binary_trees_shared_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS) $(NO_BUILTIN_CXXFLAGS) +binary_trees_shared_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS) +binary_trees_shared_LDADD = libtcmalloc_minimal.la $(PTHREAD_LIBS) endif !MINGW ### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker) diff --git a/benchmark/binary_trees.cc b/benchmark/binary_trees.cc new file mode 100644 index 0000000..5070797 --- /dev/null +++ b/benchmark/binary_trees.cc @@ -0,0 +1,106 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- +// +// Copied from +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=gpp&id=2 +// and slightly modified (particularly by adding multi-threaded +// operation to hit malloc harder). +// +// This version of binary trees is mostly new/delete benchmark +// +// NOTE: copyright of this code is unclear, but we only distribute +// source. + +/* The Computer Language Benchmarks Game + * http://benchmarksgame.alioth.debian.org/ + * + * Contributed by Jon Harrop + * Modified by Alex Mizrahi + * Adapted for gperftools and added threads by Aliaksei Kandratsenka + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct Node { + Node *l, *r; + int i; + Node(int i2) : l(0), r(0), i(i2) {} + Node(Node *l2, int i2, Node *r2) : l(l2), r(r2), i(i2) {} + ~Node() { delete l; delete r; } + int check() const { + if (l) + return l->check() + i - r->check(); + else return i; + } +}; + +Node *make(int i, int d) { + if (d == 0) return new Node(i); + return new Node(make(2*i-1, d-1), i, make(2*i, d-1)); +} + +void run(int given_depth) { + int min_depth = 4, + max_depth = std::max(min_depth+2, + given_depth), + stretch_depth = max_depth+1; + + { + Node *c = make(0, stretch_depth); + std::cout << "stretch tree of depth " << stretch_depth << "\t " + << "check: " << c->check() << std::endl; + delete c; + } + + Node *long_lived_tree=make(0, max_depth); + + for (int d=min_depth; d<=max_depth; d+=2) { + int iterations = 1 << (max_depth - d + min_depth), c=0; + for (int i=1; i<=iterations; ++i) { + Node *a = make(i, d), *b = make(-i, d); + c += a->check() + b->check(); + delete a; + delete b; + } + std::cout << (2*iterations) << "\t trees of depth " << d << "\t " + << "check: " << c << std::endl; + } + + std::cout << "long lived tree of depth " << max_depth << "\t " + << "check: " << (long_lived_tree->check()) << "\n"; + + delete long_lived_tree; +} + +static void *run_tramp(void *_a) { + intptr_t a = reinterpret_cast(_a); + run(a); + return 0; +} + +int main(int argc, char *argv[]) { + int given_depth = argc >= 2 ? atoi(argv[1]) : 20; + int thread_count = std::max(1, argc >= 3 ? atoi(argv[2]) : 1) - 1; + std::vector threads(thread_count); + + for (int i = 0; i < thread_count; i++) { + int rv = pthread_create(&threads[i], NULL, + run_tramp, + reinterpret_cast(given_depth)); + if (rv) { + errno = rv; + perror("pthread_create"); + } + } + run_tramp(reinterpret_cast(given_depth)); + for (int i = 0; i < thread_count; i++) { + pthread_join(threads[i], NULL); + } + return 0; +}