| OLD | NEW |
| (Empty) |
| 1 // Copyright 2009 The RE2 Authors. All Rights Reserved. | |
| 2 // Use of this source code is governed by a BSD-style | |
| 3 // license that can be found in the LICENSE file. | |
| 4 | |
| 5 #include "util/util.h" | |
| 6 #include "util/flags.h" | |
| 7 #include "util/benchmark.h" | |
| 8 #include "re2/re2.h" | |
| 9 | |
| 10 DEFINE_string(test_tmpdir, "/var/tmp", "temp directory"); | |
| 11 | |
| 12 using testing::Benchmark; | |
| 13 using namespace re2; | |
| 14 | |
| 15 static Benchmark* benchmarks[10000]; | |
| 16 static int nbenchmarks; | |
| 17 | |
| 18 void Benchmark::Register() { | |
| 19 benchmarks[nbenchmarks] = this; | |
| 20 if(lo < 1) | |
| 21 lo = 1; | |
| 22 if(hi < lo) | |
| 23 hi = lo; | |
| 24 nbenchmarks++; | |
| 25 } | |
| 26 | |
| 27 static int64 nsec() { | |
| 28 #if defined(__APPLE__) | |
| 29 struct timeval tv; | |
| 30 if(gettimeofday(&tv, 0) < 0) | |
| 31 return -1; | |
| 32 return (int64)tv.tv_sec*1000*1000*1000 + tv.tv_usec*1000; | |
| 33 #elif defined(_WIN32) | |
| 34 // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408.asp
x | |
| 35 // describes how to query ticks and convert to microseconds. Of course, | |
| 36 // what we want in this case are nanoseconds. Also, note that .QuadPart | |
| 37 // is a signed 64-bit integer, so casting to int64 shouldn't be needed. | |
| 38 LARGE_INTEGER freq; | |
| 39 QueryPerformanceFrequency(&freq); | |
| 40 LARGE_INTEGER ticks; | |
| 41 QueryPerformanceCounter(&ticks); | |
| 42 ticks.QuadPart *= 1000*1000*1000; | |
| 43 ticks.QuadPart /= freq.QuadPart; | |
| 44 return ticks.QuadPart; | |
| 45 #else | |
| 46 struct timespec tp; | |
| 47 if(clock_gettime(CLOCK_REALTIME, &tp) < 0) | |
| 48 return -1; | |
| 49 return (int64)tp.tv_sec*1000*1000*1000 + tp.tv_nsec; | |
| 50 #endif | |
| 51 } | |
| 52 | |
| 53 static int64 bytes; | |
| 54 static int64 ns; | |
| 55 static int64 t0; | |
| 56 static int64 items; | |
| 57 | |
| 58 void SetBenchmarkBytesProcessed(long long x) { | |
| 59 bytes = x; | |
| 60 } | |
| 61 | |
| 62 void StopBenchmarkTiming() { | |
| 63 if(t0 != 0) | |
| 64 ns += nsec() - t0; | |
| 65 t0 = 0; | |
| 66 } | |
| 67 | |
| 68 void StartBenchmarkTiming() { | |
| 69 if(t0 == 0) | |
| 70 t0 = nsec(); | |
| 71 } | |
| 72 | |
| 73 void SetBenchmarkItemsProcessed(int n) { | |
| 74 items = n; | |
| 75 } | |
| 76 | |
| 77 void BenchmarkMemoryUsage() { | |
| 78 // TODO(rsc): Implement. | |
| 79 } | |
| 80 | |
| 81 int NumCPUs() { | |
| 82 return 1; | |
| 83 } | |
| 84 | |
| 85 static void runN(Benchmark *b, int n, int siz) { | |
| 86 bytes = 0; | |
| 87 items = 0; | |
| 88 ns = 0; | |
| 89 t0 = nsec(); | |
| 90 if(b->fn) | |
| 91 b->fn(n); | |
| 92 else if(b->fnr) | |
| 93 b->fnr(n, siz); | |
| 94 else { | |
| 95 fprintf(stderr, "%s: missing function\n", b->name); | |
| 96 exit(2); | |
| 97 } | |
| 98 if(t0 != 0) | |
| 99 ns += nsec() - t0; | |
| 100 } | |
| 101 | |
| 102 static int round(int n) { | |
| 103 int base = 1; | |
| 104 | |
| 105 while(base*10 < n) | |
| 106 base *= 10; | |
| 107 if(n < 2*base) | |
| 108 return 2*base; | |
| 109 if(n < 5*base) | |
| 110 return 5*base; | |
| 111 return 10*base; | |
| 112 } | |
| 113 | |
| 114 void RunBench(Benchmark* b, int nthread, int siz) { | |
| 115 int n, last; | |
| 116 | |
| 117 // TODO(rsc): Threaded benchmarks. | |
| 118 if(nthread != 1) | |
| 119 return; | |
| 120 | |
| 121 // run once in case it's expensive | |
| 122 n = 1; | |
| 123 runN(b, n, siz); | |
| 124 while(ns < (int)1e9 && n < (int)1e9) { | |
| 125 last = n; | |
| 126 if(ns/n == 0) | |
| 127 n = (int)1e9; | |
| 128 else | |
| 129 n = (int)1e9 / static_cast<int>(ns/n); | |
| 130 | |
| 131 n = max(last+1, min(n+n/2, 100*last)); | |
| 132 n = round(n); | |
| 133 runN(b, n, siz); | |
| 134 } | |
| 135 | |
| 136 char mb[100]; | |
| 137 char suf[100]; | |
| 138 mb[0] = '\0'; | |
| 139 suf[0] = '\0'; | |
| 140 if(ns > 0 && bytes > 0) | |
| 141 snprintf(mb, sizeof mb, "\t%7.2f MB/s", ((double)bytes/1e6)/((do
uble)ns/1e9)); | |
| 142 if(b->fnr || b->lo != b->hi) { | |
| 143 if(siz >= (1<<20)) | |
| 144 snprintf(suf, sizeof suf, "/%dM", siz/(1<<20)); | |
| 145 else if(siz >= (1<<10)) | |
| 146 snprintf(suf, sizeof suf, "/%dK", siz/(1<<10)); | |
| 147 else | |
| 148 snprintf(suf, sizeof suf, "/%d", siz); | |
| 149 } | |
| 150 printf("%s%s\t%8lld\t%10lld ns/op%s\n", b->name, suf, (long long)n, (lon
g long)ns/n, mb); | |
| 151 fflush(stdout); | |
| 152 } | |
| 153 | |
| 154 static int match(const char* name, int argc, const char** argv) { | |
| 155 if(argc == 1) | |
| 156 return 1; | |
| 157 for(int i = 1; i < argc; i++) | |
| 158 if(RE2::PartialMatch(name, argv[i])) | |
| 159 return 1; | |
| 160 return 0; | |
| 161 } | |
| 162 | |
| 163 int main(int argc, const char** argv) { | |
| 164 for(int i = 0; i < nbenchmarks; i++) { | |
| 165 Benchmark* b = benchmarks[i]; | |
| 166 if(match(b->name, argc, argv)) | |
| 167 for(int j = b->threadlo; j <= b->threadhi; j++) | |
| 168 for(int k = max(b->lo, 1); k <= max(b->hi, 1); k
<<=1) | |
| 169 RunBench(b, j, k); | |
| 170 } | |
| 171 } | |
| 172 | |
| OLD | NEW |