1 #ifndef _BENCHMARK_H_ 2 #define _BENCHMARK_H_ 3 4 #include "event_counter.h" 5 6 /* 7 * Prints the best number of operations per cycle where 8 * test is the function call, answer is the expected answer generated by 9 * test, repeat is the number of times we should repeat and size is the 10 * number of operations represented by test. 11 */ 12 #define BEST_TIME(name, test, expected, pre, repeat, size, verbose) \ 13 do { \ 14 if (verbose) \ 15 std::printf("%-40s\t: ", name); \ 16 else \ 17 std::printf("\"%-40s\"", name); \ 18 fflush(NULL); \ 19 event_collector collector; \ 20 event_aggregate aggregate{}; \ 21 for (decltype(repeat) i = 0; i < repeat; i++) { \ 22 pre; \ 23 std::atomic_thread_fence(std::memory_order_acquire); \ 24 collector.start(); \ 25 if (test != expected) { \ 26 std::fprintf(stderr, "not expected (%d , %d )", (int)test, \ 27 (int)expected); \ 28 break; \ 29 } \ 30 std::atomic_thread_fence(std::memory_order_release); \ 31 event_count allocate_count = collector.end(); \ 32 aggregate << allocate_count; \ 33 } \ 34 if (collector.has_events()) { \ 35 std::printf("%7.3f", \ 36 aggregate.best.cycles() / static_cast<double>(size)); \ 37 if (verbose) { \ 38 std::printf(" cycles/byte "); \ 39 } \ 40 std::printf("\t"); \ 41 std::printf("%7.3f", \ 42 aggregate.best.instructions() / static_cast<double>(size)); \ 43 if (verbose) { \ 44 std::printf(" instructions/byte "); \ 45 } \ 46 std::printf("\t"); \ 47 } \ 48 double gb = static_cast<double>(size) / 1000000000.0; \ 49 std::printf("%7.3f", gb / aggregate.best.elapsed_sec()); \ 50 if (verbose) { \ 51 std::printf(" GB/s "); \ 52 } \ 53 std::printf("\t"); \ 54 std::printf("%7.3f", 1.0 / aggregate.best.elapsed_sec()); \ 55 if (verbose) { \ 56 std::printf(" documents/s "); \ 57 } \ 58 std::printf("\n"); \ 59 std::fflush(NULL); \ 60 } while (0) 61 62 // like BEST_TIME, but no check 63 #define BEST_TIME_NOCHECK(name, test, pre, repeat, size, verbose) \ 64 do { \ 65 if (verbose) \ 66 std::printf("%-40s\t: ", name); \ 67 else \ 68 std::printf("\"%-40s\"", name); \ 69 std::fflush(NULL); \ 70 event_collector collector; \ 71 event_aggregate aggregate{}; \ 72 for (decltype(repeat) i = 0; i < repeat; i++) { \ 73 pre; \ 74 std::atomic_thread_fence(std::memory_order_acquire); \ 75 collector.start(); \ 76 test; \ 77 std::atomic_thread_fence(std::memory_order_release); \ 78 event_count allocate_count = collector.end(); \ 79 aggregate << allocate_count; \ 80 } \ 81 if (collector.has_events()) { \ 82 std::printf("%7.3f", \ 83 aggregate.best.cycles() / static_cast<double>(size)); \ 84 if (verbose) { \ 85 std::printf(" cycles/byte "); \ 86 } \ 87 std::printf("\t"); \ 88 std::printf("%7.3f", \ 89 aggregate.best.instructions() / static_cast<double>(size)); \ 90 if (verbose) { \ 91 std::printf(" instructions/byte "); \ 92 } \ 93 std::printf("\t"); \ 94 } \ 95 double gb = static_cast<double>(size) / 1000000000.0; \ 96 std::printf("%7.3f", gb / aggregate.best.elapsed_sec()); \ 97 if (verbose) { \ 98 std::printf(" GB/s "); \ 99 } \ 100 std::printf("\t"); \ 101 std::printf("%7.3f", 1.0 / aggregate.best.elapsed_sec()); \ 102 if (verbose) { \ 103 std::printf(" documents/s "); \ 104 } \ 105 std::printf("\n"); \ 106 std::fflush(NULL); \ 107 } while (0) 108 109 #endif 110