forked from duckdb/duckdb
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathrun_benchmark_simple.py
More file actions
180 lines (135 loc) · 6.04 KB
/
Copy pathrun_benchmark_simple.py
File metadata and controls
180 lines (135 loc) · 6.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import os
import subprocess
import csv
import matplotlib.pyplot as plt
import argparse
def clean_page_cache():
"""
Clean the system page cache using the sync command and writing to /proc/sys/vm/drop_caches
Requires root privileges (sudo) to execute successfully
"""
cmd = "sudo bash -c \"sync; echo 3 > /proc/sys/vm/drop_caches\""
if verbose:
print(cmd)
os.system(cmd)
def run_benchmark(benchmark_path, draw=0):
"""
Run benchmark tests on all .benchmark files in the specified directory
Args:
benchmark_path (str): Path to directory containing benchmark files
draw (int): Flag to enable result plotting (1 = enable, 0 = disable)
"""
# Verify the provided path is a valid directory
if not os.path.isdir(benchmark_path):
print(f"Error: {benchmark_path} is not a valid path")
return
# Get last two parts of the path to use as output filename
path_parts = os.path.normpath(benchmark_path).split(os.sep)
output_name = f"{path_parts[-2]}_{path_parts[-1]}"
output_csv = "output/"+f"{output_name}.csv"
results = []
# Traverse through all files in the directory
for root, dirs, files in os.walk(benchmark_path):
# Sort files ending with .benchmark by numeric part in filename
files = sorted([file for file in files if file.endswith('.benchmark')],
key=lambda x: int(x[1:3]))
print(files)
for file in files:
if file.endswith('.benchmark'):
# Construct full file path
benchmark_file = os.path.join(root, file)
# Execute benchmark command and capture output
try:
# Build command with --disable-timeout parameter
cmd = f"{os.path.join(pixels_home, 'cpp/build/release/benchmark/benchmark_runner')} \"{benchmark_file}\" --disable-timeout --Nruns={nRuns}"
if verbose:
print(cmd)
output = subprocess.getoutput(cmd)
# Collect all run results
run_times = []
print(output)
for line in output.splitlines():
if line.startswith('Result:'):
time = float(line.split()[1])
run_times.append(time)
if verbose:
print(f"File {file} runtime: {time}")
# Save all run times if results exist
if run_times:
# Store filename and all run times
results.append((file, run_times))
if verbose:
print(f"File {file} results: {run_times}")
else:
if verbose:
print(f"No results found for file {file}")
except Exception as e:
print(f"An error {e} ocurred whne running {benchmark_file}")
# Save results to CSV file
with open(output_csv, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
# Write header: benchmark name + columns for each run
max_runs = max(len(times) for _, times in results) if results else 0
header = ['Benchmark'] + [f'Run {i+1} Time(s)' for i in range(max_runs)]
writer.writerow(header)
# Write all run results for each benchmark
for file, times in results:
# Ensure consistent column count per row
row = [file] + times + [''] * (max_runs - len(times))
writer.writerow(row)
print(f"oupput has saved in {output_csv}")
# Generate plot if requested
if draw:
plot_results(output_name, results)
def plot_results(title, results):
"""
Generate a bar chart from benchmark results showing average run times
Args:
title (str): Title for the plot (used in chart title and filename)
results (list): List of tuples containing (filename, run_times)
"""
# Extract benchmark names and calculate average times
benchmarks = [r[0].split('.')[0] for r in results]
# Calculate average time for each benchmark
avg_times = [sum(r[1])/len(r[1]) for r in results]
# Create the plot
plt.figure(figsize=(10, 6))
plt.bar(benchmarks, avg_times, color='skyblue')
plt.xlabel('Benchmarks')
plt.ylabel('Average Time (s)')
plt.title(f'{title} Results')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig("output/"+f"{title}.png")
plt.show()
print(f"Chart saved as {title}.png")
if __name__ == "__main__":
# Global variables for configuration
global pixels_home
global verbose
global nRuns
# Get PIXELS_SRC environment variable
pixels_home = os.environ.get('PIXELS_SRC')
current_dir = os.getcwd()
# Create output directory if it doesn't exist
os.makedirs(os.path.join(current_dir, "output"), exist_ok=True)
# Parse command line arguments
parser = argparse.ArgumentParser(description="Run benchmark tests and save results.")
parser.add_argument('--dir', type=str, required=True, help='Directory containing benchmark files')
parser.add_argument('--draw', type=int, default=0, choices=[0, 1],
help='Draw chart: 1 = yes, 0 = no (default: 0)')
parser.add_argument('--from-page-cache', help='Whether to read files from page cache',
type=int, default=0, choices=[0,1])
parser.add_argument('--v', dest='verbose', help='Output commands',
type=int, default=1, choices=[0,1])
parser.add_argument('--nRuns', type=int, default=1, help='Number of times to run each benchmark')
args = parser.parse_args()
# Initialize configuration from arguments
from_page_cache = args.from_page_cache
verbose = args.verbose
nRuns = args.nRuns
# Clean page cache if not reading from cache
if not from_page_cache:
clean_page_cache()
# Run benchmarks with provided arguments
run_benchmark(args.dir, args.draw)