runner/run.py

128 lines
3.2 KiB
Python
Executable File

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
import logging
import re
import subprocess
from csv import DictWriter
CONFIGS = [
'DEFAULT',
'HARDENED_USERCOPY',
'MEMCG',
'PAGE_TABLE_ISOLATION',
'RETPOLINE',
'SLAB_FREELIST_RANDOM',
'TRANSPARENT_HUGEPAGE_ALWAYS',
'USERFAULTFD',
]
PASSES = 5
VERSION = '5.5.2'
pattern = re.compile(r'(\w+) ?(.*) (\d+)us')
def load_current():
with open('current', 'r') as f:
return f.read()
def set_current(current):
with open('current', 'w') as f:
return f.write(current)
def run_bench_script():
result = subprocess.run(['bash', 'run_bench.sh'], capture_output=True)
return result.stdout.decode('UTF-8')
def parse_results(output):
results = {}
for line in output.split('\n'):
matches = pattern.match(line.strip())
if matches is None:
continue
results[matches.group(1)] = {
'params': matches.group(2),
'time': int(matches.group(3)),
}
return results
def accumulate(accumulated_results, results):
for key, value in results.items():
if key in accumulated_results:
accumulated_results[key]['time'] += value['time']
else:
accumulated_results[key] = value.copy()
def average(accumulated_results):
results = []
for key, value in accumulated_results.items():
results.append({
'name': key,
'params': value['params'],
'time': int(value['time'] / PASSES),
})
return results
def save_results(current, results):
logging.info(f'saving results: {results}')
with open(f'output/{current}.csv', 'w', newline='') as csvfile:
fieldnames = ['name', 'params', 'time']
writer = DictWriter(csvfile, fieldnames=fieldnames, delimiter=',')
writer.writeheader()
writer.writerows(results)
def prepare_next(current):
current_index = CONFIGS.index(current)
if current_index == len(CONFIGS) - 1:
return False
next = CONFIGS[current_index + 1]
logging.info(f'Setting {next} as next config')
package = f'/home/pavle/compiled/linux-{VERSION}-{next}.pkg.tar.zst'
set_current(next)
subprocess.run(['sudo', 'pacman', '-U', '--noconfirm', package])
subprocess.run(['sudo', 'efibootmgr', '-n', '0007'])
return True
def run_benchmark(current):
accumulated_results = {}
for i in range(PASSES):
logging.info(f'pass {i+1} of {PASSES}')
output = run_bench_script()
logging.debug(f'raw benchmark output: {output}')
results = parse_results(output)
accumulate(accumulated_results, results)
logging.debug(f'pass results: {results}')
logging.debug(f'accumulated results: {accumulated_results}')
final_results = average(accumulated_results)
logging.debug(f'Final results: {final_results}')
save_results(current, final_results)
def main():
current = load_current()
logging.info(f'Current config: {current}')
run_benchmark(current)
if prepare_next(current):
subprocess.run(['sudo', 'reboot'])
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
main()