15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2009 The RE2 Authors.  All Rights Reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// license that can be found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/flags.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/benchmark.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "re2/re2.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_string(test_tmpdir, "/var/tmp", "temp directory");
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Benchmark;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace re2;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Benchmark* benchmarks[10000];
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nbenchmarks;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Benchmark::Register() {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	benchmarks[nbenchmarks] = this;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(lo < 1)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		lo = 1;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(hi < lo)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		hi = lo;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	nbenchmarks++;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 nsec() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct timeval tv;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(gettimeofday(&tv, 0) < 0)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (int64)tv.tv_sec*1000*1000*1000 + tv.tv_usec*1000;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 bytes;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 ns;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 t0;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 items;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetBenchmarkBytesProcessed(long long x) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	bytes = x;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StopBenchmarkTiming() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(t0 != 0)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ns += nsec() - t0;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	t0 = 0;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StartBenchmarkTiming() {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(t0 == 0)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		t0 = nsec();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetBenchmarkItemsProcessed(int n) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	items = n;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BenchmarkMemoryUsage() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	// TODO(rsc): Implement.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NumCPUs() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void runN(Benchmark *b, int n, int siz) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	bytes = 0;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	items = 0;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ns = 0;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	t0 = nsec();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(b->fn)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		b->fn(n);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else if(b->fnr)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		b->fnr(n, siz);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		fprintf(stderr, "%s: missing function\n", b->name);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		exit(2);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(t0 != 0)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ns += nsec() - t0;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int round(int n) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int base = 1;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while(base*10 < n)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		base *= 10;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(n < 2*base)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return 2*base;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(n < 5*base)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return 5*base;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 10*base;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunBench(Benchmark* b, int nthread, int siz) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int n, last;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	// TODO(rsc): Threaded benchmarks.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(nthread != 1)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	// run once in case it's expensive
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	n = 1;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	runN(b, n, siz);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while(ns < (int)1e9 && n < (int)1e9) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		last = n;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if(ns/n == 0)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			n = 1e9;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		else
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			n = 1e9 / (ns/n);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		n = max(last+1, min(n+n/2, 100*last));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		n = round(n);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		runN(b, n, siz);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char mb[100];
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char suf[100];
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	mb[0] = '\0';
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	suf[0] = '\0';
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(ns > 0 && bytes > 0)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		snprintf(mb, sizeof mb, "\t%7.2f MB/s", ((double)bytes/1e6)/((double)ns/1e9));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(b->fnr || b->lo != b->hi) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if(siz >= (1<<20))
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			snprintf(suf, sizeof suf, "/%dM", siz/(1<<20));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		else if(siz >= (1<<10))
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			snprintf(suf, sizeof suf, "/%dK", siz/(1<<10));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		else
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			snprintf(suf, sizeof suf, "/%d", siz);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	printf("%s%s\t%8lld\t%10lld ns/op%s\n", b->name, suf, (long long)n, (long long)ns/n, mb);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fflush(stdout);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int match(const char* name, int argc, const char** argv) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(argc == 1)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return 1;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for(int i = 1; i < argc; i++)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if(RE2::PartialMatch(name, argv[i]))
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return 1;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, const char** argv) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for(int i = 0; i < nbenchmarks; i++) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		Benchmark* b = benchmarks[i];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if(match(b->name, argc, argv))
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			for(int j = b->threadlo; j <= b->threadhi; j++)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				for(int k = max(b->lo, 1); k <= max(b->hi, 1); k<<=1)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					RunBench(b, j, k);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154