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 |