blob: 586c26ac01d24eb7ecb270dd3ea6880bddbaebd2 [file] [log] [blame]
Martin Hořeňovský08371322017-02-12 12:25:43 +01001#!/usr/bin/env python
2
3from __future__ import print_function
Martin Hořeňovský26df0782017-02-08 14:14:01 +01004
5import time, subprocess, sys, os, shutil, glob, random
6import argparse
Martin Hořeňovský08371322017-02-12 12:25:43 +01007
8def median(lst):
9 lst = sorted(lst)
10 mid, odd = divmod(len(lst), 2)
11 if odd:
12 return lst[mid]
13 else:
14 return (lst[mid - 1] + lst[mid]) / 2.0
Martin Hořeňovský26df0782017-02-08 14:14:01 +010015
Martin Hořeňovský20491132017-02-14 15:34:00 +010016def mean(lst):
17 return float(sum(lst)) / max(len(lst), 1)
18
Martin Hořeňovský26df0782017-02-08 14:14:01 +010019compiler_path = ''
Martin Hořeňovský6da5e082017-02-14 15:34:17 +010020flags = []
Martin Hořeňovský26df0782017-02-08 14:14:01 +010021
22main_file = r'''
23#define CATCH_CONFIG_MAIN
24#include "catch.hpp"
25'''
26main_name = 'catch-main.cpp'
27
28dir_name = 'benchmark-dir'
29
30files = 20
31test_cases_in_file = 20
32sections_in_file = 4
33assertions_per_section = 5
34
35checks = [
36 'a != b', 'a != c', 'a != d', 'a != e', 'b != c', 'b != d', 'b != e', 'c != d', 'c != e', 'd != e', 'a + a == a',
37 'a + b == b', 'a + c == c', 'a + d == d', 'a + e == e', 'b + a == b', 'b + b == c', 'b + c == d',
38 'b + d == e', 'c + a == c', 'c + b == d', 'c + c == e', 'd + a == d', 'd + b == e', 'e + a == e',
39 'a + a + a == a', 'b + c == a + d', 'c + a + a == a + b + b + a',
40 'a < b', 'b < c', 'c < d', 'd < e', 'a >= a', 'd >= b',
41]
42
43def create_temp_dir():
44 if os.path.exists(dir_name):
45 shutil.rmtree(dir_name)
46 os.mkdir(dir_name)
47
48def copy_catch(path_to_catch):
49 shutil.copy(path_to_catch, dir_name)
50
51def create_catch_main():
52 with open(main_name, 'w') as f:
53 f.write(main_file)
54
55def compile_main():
Martin Hořeňovský08371322017-02-12 12:25:43 +010056 start_t = time.time()
Martin Hořeňovský6da5e082017-02-14 15:34:17 +010057 subprocess.check_call([compiler_path, main_name, '-c'] + flags)
Martin Hořeňovský08371322017-02-12 12:25:43 +010058 end_t = time.time()
Martin Hořeňovský26df0782017-02-08 14:14:01 +010059 return end_t - start_t
60
61def compile_files():
Martin Hořeňovský97edf7c2017-08-30 18:11:52 +020062 cpp_files = glob.glob('tests*.cpp')
Martin Hořeňovský08371322017-02-12 12:25:43 +010063 start_t = time.time()
Martin Hořeňovský6da5e082017-02-14 15:34:17 +010064 subprocess.check_call([compiler_path, '-c'] + flags + cpp_files)
Martin Hořeňovský08371322017-02-12 12:25:43 +010065 end_t = time.time()
Martin Hořeňovský26df0782017-02-08 14:14:01 +010066 return end_t - start_t
67
68def link_files():
69 obj_files = glob.glob('*.o')
Martin Hořeňovský08371322017-02-12 12:25:43 +010070 start_t = time.time()
Martin Hořeňovský6da5e082017-02-14 15:34:17 +010071 subprocess.check_call([compiler_path] + flags + obj_files)
Martin Hořeňovský08371322017-02-12 12:25:43 +010072 end_t = time.time()
Martin Hořeňovský26df0782017-02-08 14:14:01 +010073 return end_t - start_t
74
75def benchmark(func):
Martin Hořeňovský20491132017-02-14 15:34:00 +010076 results = [func() for i in range(10)]
77 return mean(results), median(results)
Martin Hořeňovský26df0782017-02-08 14:14:01 +010078
79def char_range(start, end):
80 for c in range(ord(start), ord(end)):
81 yield chr(c)
82
83def generate_sections(fd):
84 for i in range(sections_in_file):
85 fd.write(' SECTION("Section {}") {{\n'.format(i))
86 fd.write('\n'.join(' CHECK({});'.format(check) for check in random.sample(checks, assertions_per_section)))
87 fd.write(' }\n')
88
89
90def generate_file(file_no):
91 with open('tests{}.cpp'.format(file_no), 'w') as f:
92 f.write('#include "catch.hpp"\n\n')
93 for i in range(test_cases_in_file):
94 f.write('TEST_CASE("File {} test {}", "[.compile]"){{\n'.format(file_no, i))
95 for i, c in enumerate(char_range('a', 'f')):
96 f.write(' int {} = {};\n'.format(c, i))
97 generate_sections(f)
98 f.write('}\n\n')
99
100
101def generate_files():
102 create_catch_main()
103 for i in range(files):
104 generate_file(i)
105
106
107options = ['all', 'main', 'files', 'link']
108
109parser = argparse.ArgumentParser(description='Benchmarks Catch\'s compile times against some synthetic tests')
110# Add first arg -- benchmark type
111parser.add_argument('benchmark_kind', nargs='?', default='all', choices=options, help='What kind of benchmark to run, default: all')
112
113# Args to allow changing header/compiler
114parser.add_argument('-I', '--catch-header', default='catch.hpp', help = 'Path to catch.hpp, default: catch.hpp')
115parser.add_argument('-c', '--compiler', default='g++', help = 'Compiler to use, default: g++')
116
Martin Hořeňovský97edf7c2017-08-30 18:11:52 +0200117parser.add_argument('-f', '--flags', help = 'Flags to be passed to the compiler. Pass as "," separated list')
Martin Hořeňovský6da5e082017-02-14 15:34:17 +0100118
Martin Hořeňovský26df0782017-02-08 14:14:01 +0100119# Allow creating files only, without running the whole thing
Martin Hořeňovský08371322017-02-12 12:25:43 +0100120parser.add_argument('-g', '--generate-files', action='store_true', help='Generate test files and quit')
Martin Hořeňovský26df0782017-02-08 14:14:01 +0100121
122args = parser.parse_args()
123
124compiler_path = args.compiler
125catch_path = args.catch_header
126
Martin Hořeňovský08371322017-02-12 12:25:43 +0100127if args.generate_files:
128 create_temp_dir()
129 copy_catch(catch_path)
Martin Hořeňovský374c0502017-03-06 10:59:17 +0100130 os.chdir(dir_name)
Martin Hořeňovský08371322017-02-12 12:25:43 +0100131 # now create the fake test files
132 generate_files()
133 # Early exit
Martin Hořeňovský26df0782017-02-08 14:14:01 +0100134 print('Finished generating files')
135 exit(1)
136
Martin Hořeňovskýfd6c7ae2017-03-02 18:27:31 +0100137os.chdir(dir_name)
138
Martin Hořeňovský6da5e082017-02-14 15:34:17 +0100139if args.flags:
Martin Hořeňovský97edf7c2017-08-30 18:11:52 +0200140 flags = args.flags.split(',')
Martin Hořeňovský26df0782017-02-08 14:14:01 +0100141
142print('Time needed for ...')
143if args.benchmark_kind in ('all', 'main'):
Martin Hořeňovský20491132017-02-14 15:34:00 +0100144 print(' ... compiling main, mean: {:.2f}, median: {:.2f} s'.format(*benchmark(compile_main)))
Martin Hořeňovský26df0782017-02-08 14:14:01 +0100145if args.benchmark_kind in ('all', 'files'):
Martin Hořeňovský20491132017-02-14 15:34:00 +0100146 print(' ... compiling test files, mean: {:.2f}, median: {:.2f} s'.format(*benchmark(compile_files)))
Martin Hořeňovský26df0782017-02-08 14:14:01 +0100147if args.benchmark_kind in ('all', 'link'):
Martin Hořeňovský20491132017-02-14 15:34:00 +0100148 print(' ... linking everything, mean: {:.2f}, median: {:.2f} s'.format(*benchmark(link_files)))