1ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj// Copyright 2009 The RE2 Authors.  All Rights Reserved.
2ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj// Use of this source code is governed by a BSD-style
3ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj// license that can be found in the LICENSE file.
4887a11a609f3e61d2ae8fe4e67f176207715da7esewardj
5496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj#include "util/util.h"
6ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj#include "util/flags.h"
7ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj#include "util/benchmark.h"
8ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj#include "re2/re2.h"
9f8ed9d874a7b8651654591c68c6d431c758d787csewardj
10f8ed9d874a7b8651654591c68c6d431c758d787csewardjDEFINE_string(test_tmpdir, "/var/tmp", "temp directory");
11f8ed9d874a7b8651654591c68c6d431c758d787csewardj
12f8ed9d874a7b8651654591c68c6d431c758d787csewardjusing testing::Benchmark;
13496a58d130a28ac3a5ba33c9012dabbe61dc852csewardjusing namespace re2;
14f8ed9d874a7b8651654591c68c6d431c758d787csewardj
15f8ed9d874a7b8651654591c68c6d431c758d787csewardjstatic Benchmark* benchmarks[10000];
16f8ed9d874a7b8651654591c68c6d431c758d787csewardjstatic int nbenchmarks;
17f8ed9d874a7b8651654591c68c6d431c758d787csewardj
18f8ed9d874a7b8651654591c68c6d431c758d787csewardjvoid Benchmark::Register() {
19f8ed9d874a7b8651654591c68c6d431c758d787csewardj	benchmarks[nbenchmarks] = this;
20f8ed9d874a7b8651654591c68c6d431c758d787csewardj	if(lo < 1)
21f8ed9d874a7b8651654591c68c6d431c758d787csewardj		lo = 1;
22f8ed9d874a7b8651654591c68c6d431c758d787csewardj	if(hi < lo)
23f8ed9d874a7b8651654591c68c6d431c758d787csewardj		hi = lo;
24f8ed9d874a7b8651654591c68c6d431c758d787csewardj	nbenchmarks++;
25f8ed9d874a7b8651654591c68c6d431c758d787csewardj}
26f8ed9d874a7b8651654591c68c6d431c758d787csewardj
27f8ed9d874a7b8651654591c68c6d431c758d787csewardjstatic int64 nsec() {
28f8ed9d874a7b8651654591c68c6d431c758d787csewardj	struct timeval tv;
29f8ed9d874a7b8651654591c68c6d431c758d787csewardj	if(gettimeofday(&tv, 0) < 0)
30f8ed9d874a7b8651654591c68c6d431c758d787csewardj		return -1;
31f8ed9d874a7b8651654591c68c6d431c758d787csewardj	return (int64)tv.tv_sec*1000*1000*1000 + tv.tv_usec*1000;
32f8ed9d874a7b8651654591c68c6d431c758d787csewardj}
33f8ed9d874a7b8651654591c68c6d431c758d787csewardj
34f8ed9d874a7b8651654591c68c6d431c758d787csewardjstatic int64 bytes;
35f8ed9d874a7b8651654591c68c6d431c758d787csewardjstatic int64 ns;
36887a11a609f3e61d2ae8fe4e67f176207715da7esewardjstatic int64 t0;
37887a11a609f3e61d2ae8fe4e67f176207715da7esewardjstatic int64 items;
38ac9af021b93dfe6f35c01d9c6fd15a3d67685843sewardj
39887a11a609f3e61d2ae8fe4e67f176207715da7esewardjvoid SetBenchmarkBytesProcessed(long long x) {
40ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	bytes = x;
41ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj}
42496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
43ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardjvoid StopBenchmarkTiming() {
44ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	if(t0 != 0)
45ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj		ns += nsec() - t0;
46ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	t0 = 0;
47496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj}
48496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
49496a58d130a28ac3a5ba33c9012dabbe61dc852csewardjvoid StartBenchmarkTiming() {
50496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj	if(t0 == 0)
51496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj		t0 = nsec();
52496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj}
53496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
54496a58d130a28ac3a5ba33c9012dabbe61dc852csewardjvoid SetBenchmarkItemsProcessed(int n) {
55496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj	items = n;
56496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj}
57496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
58496a58d130a28ac3a5ba33c9012dabbe61dc852csewardjvoid BenchmarkMemoryUsage() {
59496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj	// TODO(rsc): Implement.
60496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj}
61496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
62496a58d130a28ac3a5ba33c9012dabbe61dc852csewardjint NumCPUs() {
63496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj	return 1;
64496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj}
65496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj
66496a58d130a28ac3a5ba33c9012dabbe61dc852csewardjstatic void runN(Benchmark *b, int n, int siz) {
67496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj	bytes = 0;
68496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj	items = 0;
69c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	ns = 0;
70e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	t0 = nsec();
71e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	if(b->fn)
72c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		b->fn(n);
73c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	else if(b->fnr)
74c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		b->fnr(n, siz);
75c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	else {
76c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		fprintf(stderr, "%s: missing function\n", b->name);
77c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		exit(2);
78c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	}
799b96767debeeb1f78378f0e7e295fe6762c64002sewardj	if(t0 != 0)
80c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		ns += nsec() - t0;
81c9a43665879a03886b27a65b68af2a2c11b04f59sewardj}
82c9a43665879a03886b27a65b68af2a2c11b04f59sewardj
83d1725d18b61bf7912a9099686179faef5815dba1sewardjstatic int round(int n) {
84e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	int base = 1;
85e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj
8635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj	while(base*10 < n)
872d3f77c12d2911173fd182d0b6e954196dee9135sewardj		base *= 10;
88c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	if(n < 2*base)
89e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj		return 2*base;
90af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	if(n < 5*base)
91af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj		return 5*base;
92af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	return 10*base;
93af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj}
94af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj
95af1cecaf9c96f99381dda16f41d286fc3e4d220asewardjvoid RunBench(Benchmark* b, int nthread, int siz) {
96af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	int n, last;
97af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj
98af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	// TODO(rsc): Threaded benchmarks.
99af1cecaf9c96f99381dda16f41d286fc3e4d220asewardj	if(nthread != 1)
100c97096c44637ae5775ed305b19f16f0b505f17d8sewardj		return;
101ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj
102ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	// run once in case it's expensive
103c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	n = 1;
104c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	runN(b, n, siz);
105c9a43665879a03886b27a65b68af2a2c11b04f59sewardj	while(ns < (int)1e9 && n < (int)1e9) {
106c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		last = n;
107c9a43665879a03886b27a65b68af2a2c11b04f59sewardj		if(ns/n == 0)
108c9a43665879a03886b27a65b68af2a2c11b04f59sewardj			n = 1e9;
1091e6ad745ebafd0524da1da27a4b85524fa84f777sewardj		else
1101e6ad745ebafd0524da1da27a4b85524fa84f777sewardj			n = 1e9 / (ns/n);
1111e6ad745ebafd0524da1da27a4b85524fa84f777sewardj
1121e6ad745ebafd0524da1da27a4b85524fa84f777sewardj		n = max(last+1, min(n+n/2, 100*last));
1131e6ad745ebafd0524da1da27a4b85524fa84f777sewardj		n = round(n);
114207557ab2ea38239b670785c976b89d50bbb0eccsewardj		runN(b, n, siz);
115ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	}
116ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj
117ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	char mb[100];
118e3d0d2ea7b2161ae4f627882be33902ce5f3f8besewardj	char suf[100];
119ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	mb[0] = '\0';
120ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	suf[0] = '\0';
121ba99931f6dfa264d7bc7c3845a46fc955ab56d93sewardj	if(ns > 0 && bytes > 0)
122c97096c44637ae5775ed305b19f16f0b505f17d8sewardj		snprintf(mb, sizeof mb, "\t%7.2f MB/s", ((double)bytes/1e6)/((double)ns/1e9));
123c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	if(b->fnr || b->lo != b->hi) {
124c97096c44637ae5775ed305b19f16f0b505f17d8sewardj		if(siz >= (1<<20))
125c97096c44637ae5775ed305b19f16f0b505f17d8sewardj			snprintf(suf, sizeof suf, "/%dM", siz/(1<<20));
126a58ea668d4725b87a146cf43cc48b8ea6ead84casewardj		else if(siz >= (1<<10))
12717442fe8094d0f82266e5a05509f62cac8f7539esewardj			snprintf(suf, sizeof suf, "/%dK", siz/(1<<10));
1281e6ad745ebafd0524da1da27a4b85524fa84f777sewardj		else
129ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj			snprintf(suf, sizeof suf, "/%d", siz);
130ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	}
131ac6b7121413a24ce2f63727d50ac4f3a1b9027e6sewardj	printf("%s%s\t%8lld\t%10lld ns/op%s\n", b->name, suf, (long long)n, (long long)ns/n, mb);
132ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj	fflush(stdout);
133ba99931f6dfa264d7bc7c3845a46fc955ab56d93sewardj}
13417442fe8094d0f82266e5a05509f62cac8f7539esewardj
13517442fe8094d0f82266e5a05509f62cac8f7539esewardjstatic int match(const char* name, int argc, const char** argv) {
13617442fe8094d0f82266e5a05509f62cac8f7539esewardj	if(argc == 1)
13717442fe8094d0f82266e5a05509f62cac8f7539esewardj		return 1;
13817442fe8094d0f82266e5a05509f62cac8f7539esewardj	for(int i = 1; i < argc; i++)
13917442fe8094d0f82266e5a05509f62cac8f7539esewardj		if(RE2::PartialMatch(name, argv[i]))
1401e6ad745ebafd0524da1da27a4b85524fa84f777sewardj			return 1;
141c97096c44637ae5775ed305b19f16f0b505f17d8sewardj	return 0;
142695cff9303ef5dc8079117acfd632b44edb1f010sewardj}
143695cff9303ef5dc8079117acfd632b44edb1f010sewardj
14435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardjint main(int argc, const char** argv) {
1454345f7a3ecee1dde39b3c9b58372a5af97a06e8csewardj	for(int i = 0; i < nbenchmarks; i++) {
146ec6ad593611ccd69f797e3add4d23a5f31aa84d6sewardj		Benchmark* b = benchmarks[i];
147c97096c44637ae5775ed305b19f16f0b505f17d8sewardj		if(match(b->name, argc, argv))
1488ea867b06de73d909c29e243407713c291c8414esewardj			for(int j = b->threadlo; j <= b->threadhi; j++)
1498ea867b06de73d909c29e243407713c291c8414esewardj				for(int k = max(b->lo, 1); k <= max(b->hi, 1); k<<=1)
1508ea867b06de73d909c29e243407713c291c8414esewardj					RunBench(b, j, k);
15177352545d8416a36a4e6310aaea6b0205508aea2sewardj	}
1528ea867b06de73d909c29e243407713c291c8414esewardj}
1538ea867b06de73d909c29e243407713c291c8414esewardj
1548ea867b06de73d909c29e243407713c291c8414esewardj