Brian Silverman | 20350ac | 2021-11-17 18:19:55 -0800 | [diff] [blame] | 1 | // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- |
| 2 | // |
| 3 | // Copied from |
| 4 | // http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=gpp&id=2 |
| 5 | // and slightly modified (particularly by adding multi-threaded |
| 6 | // operation to hit malloc harder). |
| 7 | // |
| 8 | // This version of binary trees is mostly new/delete benchmark |
| 9 | // |
| 10 | // NOTE: copyright of this code is unclear, but we only distribute |
| 11 | // source. |
| 12 | |
| 13 | /* The Computer Language Benchmarks Game |
| 14 | * http://benchmarksgame.alioth.debian.org/ |
| 15 | * |
| 16 | * Contributed by Jon Harrop |
| 17 | * Modified by Alex Mizrahi |
| 18 | * Adapted for gperftools and added threads by Aliaksei Kandratsenka |
| 19 | */ |
| 20 | |
| 21 | #include <algorithm> |
| 22 | #include <errno.h> |
| 23 | #include <iostream> |
| 24 | #include <pthread.h> |
| 25 | #include <stdint.h> |
| 26 | #include <stdio.h> |
| 27 | #include <stdlib.h> |
| 28 | #include <vector> |
| 29 | |
| 30 | struct Node { |
| 31 | Node *l, *r; |
| 32 | int i; |
| 33 | Node(int i2) : l(0), r(0), i(i2) {} |
| 34 | Node(Node *l2, int i2, Node *r2) : l(l2), r(r2), i(i2) {} |
| 35 | ~Node() { delete l; delete r; } |
| 36 | int check() const { |
| 37 | if (l) { |
| 38 | return l->check() + i - r->check(); |
| 39 | } else { |
| 40 | return i; |
| 41 | } |
| 42 | } |
| 43 | }; |
| 44 | |
| 45 | Node *make(int i, int d) { |
| 46 | if (d == 0) return new Node(i); |
| 47 | return new Node(make(2*i-1, d-1), i, make(2*i, d-1)); |
| 48 | } |
| 49 | |
| 50 | void run(int given_depth) { |
| 51 | int min_depth = 4, |
| 52 | max_depth = std::max(min_depth+2, |
| 53 | given_depth), |
| 54 | stretch_depth = max_depth+1; |
| 55 | |
| 56 | { |
| 57 | Node *c = make(0, stretch_depth); |
| 58 | std::cout << "stretch tree of depth " << stretch_depth << "\t " |
| 59 | << "check: " << c->check() << std::endl; |
| 60 | delete c; |
| 61 | } |
| 62 | |
| 63 | Node *long_lived_tree=make(0, max_depth); |
| 64 | |
| 65 | for (int d=min_depth; d<=max_depth; d+=2) { |
| 66 | int iterations = 1 << (max_depth - d + min_depth), c=0; |
| 67 | for (int i=1; i<=iterations; ++i) { |
| 68 | Node *a = make(i, d), *b = make(-i, d); |
| 69 | c += a->check() + b->check(); |
| 70 | delete a; |
| 71 | delete b; |
| 72 | } |
| 73 | std::cout << (2*iterations) << "\t trees of depth " << d << "\t " |
| 74 | << "check: " << c << std::endl; |
| 75 | } |
| 76 | |
| 77 | std::cout << "long lived tree of depth " << max_depth << "\t " |
| 78 | << "check: " << (long_lived_tree->check()) << "\n"; |
| 79 | |
| 80 | delete long_lived_tree; |
| 81 | } |
| 82 | |
| 83 | static void *run_tramp(void *_a) { |
| 84 | intptr_t a = reinterpret_cast<intptr_t>(_a); |
| 85 | run(a); |
| 86 | return 0; |
| 87 | } |
| 88 | |
| 89 | int main(int argc, char *argv[]) { |
| 90 | int given_depth = argc >= 2 ? atoi(argv[1]) : 20; |
| 91 | int thread_count = std::max(1, argc >= 3 ? atoi(argv[2]) : 1) - 1; |
| 92 | std::vector<pthread_t> threads(thread_count); |
| 93 | |
| 94 | for (int i = 0; i < thread_count; i++) { |
| 95 | int rv = pthread_create(&threads[i], NULL, |
| 96 | run_tramp, |
| 97 | reinterpret_cast<void *>(given_depth)); |
| 98 | if (rv) { |
| 99 | errno = rv; |
| 100 | perror("pthread_create"); |
| 101 | } |
| 102 | } |
| 103 | run_tramp(reinterpret_cast<void *>(given_depth)); |
| 104 | for (int i = 0; i < thread_count; i++) { |
| 105 | pthread_join(threads[i], NULL); |
| 106 | } |
| 107 | return 0; |
| 108 | } |