128 lines
3.2 KiB
Python
Executable File
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()
|