diff --git a/runners/bench_runner.c b/runners/bench_runner.c index 474d2fcb..352ec7bc 100644 --- a/runners/bench_runner.c +++ b/runners/bench_runner.c @@ -432,8 +432,8 @@ bench_flags_t bench_mask = 0; const char *bench_disk_path = NULL; const char *bench_trace_path = NULL; bool bench_trace_backtrace = false; -uint32_t bench_trace_period = 0; -uint32_t bench_trace_freq = 0; +uint32_t bench_trace_step = 0; +uint32_t bench_trace_runfreq = 0; FILE *bench_trace_file = NULL; uint32_t bench_trace_cycles = 0; uint64_t bench_trace_time = 0; @@ -456,9 +456,9 @@ void bench_trace(const char *fmt, ...) { BENCH_HEAP_PAUSE(); if (bench_trace_path) { - // sample at a specific period? - if (bench_trace_period) { - if (bench_trace_cycles % bench_trace_period != 0) { + // sample at a specific step? + if (bench_trace_step) { + if (bench_trace_cycles % bench_trace_step != 0) { bench_trace_cycles += 1; goto done; } @@ -466,12 +466,13 @@ void bench_trace(const char *fmt, ...) { } // sample at a specific frequency? - if (bench_trace_freq) { + if (bench_trace_runfreq) { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); uint64_t now = (uint64_t)t.tv_sec*1000*1000*1000 + (uint64_t)t.tv_nsec; - if (now - bench_trace_time < (1000*1000*1000) / bench_trace_freq) { + if (now - bench_trace_time + < (1000*1000*1000) / bench_trace_runfreq) { goto done; } bench_trace_time = now; @@ -2042,21 +2043,21 @@ enum opt_flags { OPT_LIST_IMPLICIT_DEFINES = 5, OPT_DEFINE = 'D', OPT_DEFINE_DEPTH = 6, - OPT_STEP = 's', - OPT_FORCE = 7, - OPT_NO_INTERNAL = 8, - OPT_NO_LITMUS = 9, + OPT_STEP = 7, + OPT_FORCE = 8, + OPT_NO_INTERNAL = 9, + OPT_NO_LITMUS = 10, OPT_DISK = 'd', OPT_TRACE = 't', - OPT_TRACE_BACKTRACE = 10, - OPT_TRACE_PERIOD = 11, - OPT_TRACE_FREQ = 12, - OPT_READ_SLEEP = 13, - OPT_PROG_SLEEP = 14, - OPT_ERASE_SLEEP = 15, + OPT_TRACE_BACKTRACE = 11, + OPT_TRACE_STEP = 12, + OPT_TRACE_RUNFREQ = 13, + OPT_READ_SLEEP = 14, + OPT_PROG_SLEEP = 15, + OPT_ERASE_SLEEP = 16, }; -const char *short_opts = "hYlLD:s:d:t:"; +const char *short_opts = "hYlLD:d:t:"; const struct option long_opts[] = { {"help", no_argument, NULL, OPT_HELP}, @@ -2079,8 +2080,8 @@ const struct option long_opts[] = { {"disk", required_argument, NULL, OPT_DISK}, {"trace", required_argument, NULL, OPT_TRACE}, {"trace-backtrace", no_argument, NULL, OPT_TRACE_BACKTRACE}, - {"trace-period", required_argument, NULL, OPT_TRACE_PERIOD}, - {"trace-freq", required_argument, NULL, OPT_TRACE_FREQ}, + {"trace-step", required_argument, NULL, OPT_TRACE_STEP}, + {"trace-runfreq", required_argument, NULL, OPT_TRACE_RUNFREQ}, {"read-sleep", required_argument, NULL, OPT_READ_SLEEP}, {"prog-sleep", required_argument, NULL, OPT_PROG_SLEEP}, {"erase-sleep", required_argument, NULL, OPT_ERASE_SLEEP}, @@ -2106,7 +2107,7 @@ const char *const help_text[] = { "Direct block device operations to this file.", "Direct trace output to this file.", "Include a backtrace with every trace statement.", - "Sample trace output at this period in cycles.", + "Sample trace output every n steps.", "Sample trace output at this frequency in hz.", "Artificial read delay in seconds.", "Artificial prog delay in seconds.", @@ -2449,20 +2450,20 @@ int main(int argc, char **argv) { bench_trace_backtrace = true; break; - case OPT_TRACE_PERIOD:; + case OPT_TRACE_STEP:; parsed = NULL; - bench_trace_period = strtoumax(optarg, &parsed, 0); + bench_trace_step = strtoumax(optarg, &parsed, 0); if (parsed == optarg) { - fprintf(stderr, "error: invalid trace-period: %s\n", optarg); + fprintf(stderr, "error: invalid trace-step: %s\n", optarg); exit(-1); } break; - case OPT_TRACE_FREQ:; + case OPT_TRACE_RUNFREQ:; parsed = NULL; - bench_trace_freq = strtoumax(optarg, &parsed, 0); + bench_trace_runfreq = strtoumax(optarg, &parsed, 0); if (parsed == optarg) { - fprintf(stderr, "error: invalid trace-freq: %s\n", optarg); + fprintf(stderr, "error: invalid trace-runfreq: %s\n", optarg); exit(-1); } break; diff --git a/runners/test_runner.c b/runners/test_runner.c index e984bcad..621e373d 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -443,8 +443,8 @@ test_flags_t test_mask = 0; const char *test_disk_path = NULL; const char *test_trace_path = NULL; bool test_trace_backtrace = false; -uint32_t test_trace_period = 0; -uint32_t test_trace_freq = 0; +uint32_t test_trace_step = 0; +uint32_t test_trace_runfreq = 0; FILE *test_trace_file = NULL; uint32_t test_trace_cycles = 0; uint64_t test_trace_time = 0; @@ -470,9 +470,9 @@ void *test_trace_backtrace_buffer[ // trace printing void test_trace(const char *fmt, ...) { if (test_trace_path) { - // sample at a specific period? - if (test_trace_period) { - if (test_trace_cycles % test_trace_period != 0) { + // sample at a specific step? + if (test_trace_step) { + if (test_trace_cycles % test_trace_step != 0) { test_trace_cycles += 1; goto done; } @@ -480,12 +480,13 @@ void test_trace(const char *fmt, ...) { } // sample at a specific frequency? - if (test_trace_freq) { + if (test_trace_runfreq) { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); uint64_t now = (uint64_t)t.tv_sec*1000*1000*1000 + (uint64_t)t.tv_nsec; - if (now - test_trace_time < (1000*1000*1000) / test_trace_freq) { + if (now - test_trace_time + < (1000*1000*1000) / test_trace_runfreq) { goto done; } test_trace_time = now; @@ -1980,22 +1981,22 @@ enum opt_flags { OPT_DEFINE = 'D', OPT_DEFINE_DEPTH = 7, OPT_POWERLOSS = 'P', - OPT_STEP = 's', - OPT_FORCE = 8, - OPT_NO_INTERNAL = 9, - OPT_NO_REENTRANT = 10, - OPT_NO_FUZZ = 11, + OPT_STEP = 8, + OPT_FORCE = 9, + OPT_NO_INTERNAL = 10, + OPT_NO_REENTRANT = 11, + OPT_NO_FUZZ = 12, OPT_DISK = 'd', OPT_TRACE = 't', - OPT_TRACE_BACKTRACE = 12, - OPT_TRACE_PERIOD = 13, - OPT_TRACE_FREQ = 14, - OPT_READ_SLEEP = 15, - OPT_PROG_SLEEP = 16, - OPT_ERASE_SLEEP = 17, + OPT_TRACE_BACKTRACE = 13, + OPT_TRACE_STEP = 14, + OPT_TRACE_RUNFREQ = 15, + OPT_READ_SLEEP = 16, + OPT_PROG_SLEEP = 17, + OPT_ERASE_SLEEP = 18, }; -const char *short_opts = "hYlLD:P:s:d:t:"; +const char *short_opts = "hYlLD:P:d:t:"; const struct option long_opts[] = { {"help", no_argument, NULL, OPT_HELP}, @@ -2021,8 +2022,8 @@ const struct option long_opts[] = { {"disk", required_argument, NULL, OPT_DISK}, {"trace", required_argument, NULL, OPT_TRACE}, {"trace-backtrace", no_argument, NULL, OPT_TRACE_BACKTRACE}, - {"trace-period", required_argument, NULL, OPT_TRACE_PERIOD}, - {"trace-freq", required_argument, NULL, OPT_TRACE_FREQ}, + {"trace-step", required_argument, NULL, OPT_TRACE_STEP}, + {"trace-runfreq", required_argument, NULL, OPT_TRACE_RUNFREQ}, {"read-sleep", required_argument, NULL, OPT_READ_SLEEP}, {"prog-sleep", required_argument, NULL, OPT_PROG_SLEEP}, {"erase-sleep", required_argument, NULL, OPT_ERASE_SLEEP}, @@ -2051,7 +2052,7 @@ const char *const help_text[] = { "Direct block device operations to this file.", "Direct trace output to this file.", "Include a backtrace with every trace statement.", - "Sample trace output at this period in cycles.", + "Sample trace output every n steps.", "Sample trace output at this frequency in hz.", "Artificial read delay in seconds.", "Artificial prog delay in seconds.", @@ -2569,21 +2570,21 @@ int main(int argc, char **argv) { test_trace_backtrace = true; break; - case OPT_TRACE_PERIOD:; + case OPT_TRACE_STEP:; parsed = NULL; - test_trace_period = strtoumax(optarg, &parsed, 0); + test_trace_step = strtoumax(optarg, &parsed, 0); if (parsed == optarg) { - fprintf(stderr, "error: invalid trace-period: %s\n", + fprintf(stderr, "error: invalid trace-step: %s\n", optarg); exit(-1); } break; - case OPT_TRACE_FREQ:; + case OPT_TRACE_RUNFREQ:; parsed = NULL; - test_trace_freq = strtoumax(optarg, &parsed, 0); + test_trace_runfreq = strtoumax(optarg, &parsed, 0); if (parsed == optarg) { - fprintf(stderr, "error: invalid trace-freq: %s\n", optarg); + fprintf(stderr, "error: invalid trace-runfreq: %s\n", optarg); exit(-1); } break; diff --git a/scripts/bench.py b/scripts/bench.py index d1ce9424..d6818419 100755 --- a/scripts/bench.py +++ b/scripts/bench.py @@ -792,11 +792,11 @@ def find_runner(runner, id=None, main=True, **args): # run under perf? if args.get('perf'): cmd[:0] = args['perf_script'] + list(filter(None, [ - '--record', - '--perf-freq=%s' % args['perf_freq'] - if args.get('perf_freq') else None, - '--perf-period=%s' % args['perf_period'] - if args.get('perf_period') else None, + '-e', + '--perf-step=%s' % args['perf_step'] + if args.get('perf_step') else None, + '--perf-runfreq=%s' % args['perf_runfreq'] + if args.get('perf_runfreq') else None, '--perf-events=%s' % args['perf_events'] if args.get('perf_events') else None, '--perf-path=%s' % args['perf_path'] @@ -822,10 +822,10 @@ def find_runner(runner, id=None, main=True, **args): cmd.append('-t%s' % args['trace']) if args.get('trace_backtrace'): cmd.append('--trace-backtrace') - if args.get('trace_period'): - cmd.append('--trace-period=%s' % args['trace_period']) - if args.get('trace_freq'): - cmd.append('--trace-freq=%s' % args['trace_freq']) + if args.get('trace_step'): + cmd.append('--trace-step=%s' % args['trace_step']) + if args.get('trace_runfreq'): + cmd.append('--trace-runfreq=%s' % args['trace_runfreq']) if args.get('read_sleep'): cmd.append('--read-sleep=%s' % args['read_sleep']) if args.get('prog_sleep'): @@ -1305,9 +1305,9 @@ def run_stage(name, runner, bench_ids, stdout_, trace_, output_, **args): while start < total_perms: runner_ = find_runner(runner, main=main, **args) if args.get('isolate') or args.get('valgrind'): - runner_.append('-s%s,%s,%s' % (start, start+step, step)) + runner_.append('--step=%s,%s,%s' % (start, start+step, step)) elif start != 0 or step != 1: - runner_.append('-s%s,,%s' % (start, step)) + runner_.append('--step=%s,,%s' % (start, step)) runner_.extend(bench_ids) @@ -1649,6 +1649,7 @@ def main(**args): if __name__ == "__main__": import argparse import sys + import re argparse.ArgumentParser._handle_conflict_ignore = lambda *_: None argparse._ArgumentGroup._handle_conflict_ignore = lambda *_: None parser = argparse.ArgumentParser( @@ -1743,10 +1744,10 @@ if __name__ == "__main__": action='store_true', help="Include a backtrace with every trace statement.") bench_parser.add_argument( - '--trace-period', - help="Sample trace output at this period in cycles.") + '--trace-step', + help="Sample trace output every n steps.") bench_parser.add_argument( - '--trace-freq', + '--trace-runfreq', help="Sample trace output at this frequency in hz.") bench_parser.add_argument( '-O', '--stdout', @@ -1847,13 +1848,13 @@ if __name__ == "__main__": help="Run under Linux's perf to sample performance counters, " "writing samples to this file.") bench_parser.add_argument( - '--perf-freq', + '--perf-step', + help="perf sampling step. This is passed directly to the perf " + "script.") + bench_parser.add_argument( + '--perf-runfreq', help="perf sampling frequency. This is passed directly to the " "perf script.") - bench_parser.add_argument( - '--perf-period', - help="perf sampling period. This is passed directly to the perf " - "script.") bench_parser.add_argument( '--perf-events', help="perf events to record. This is passed directly to the perf " @@ -1880,27 +1881,31 @@ if __name__ == "__main__": '-c', '--compile', action='store_true', help="Compile a bench suite or source file.") - comp_parser.add_argument( - '-o', '--output', - help="Output file.") - comp_parser.add_argument( - '-s', '--source', - help="Source file to compile, possibly injecting internal benches.") - comp_parser.add_argument( - '--include', - help="Inject these header files into every compiled bench file. " - "Defaults to %r." % HEADER_PATHS) - comp_parser.add_argument( - '--no-internal', - action='store_true', - help="Don't build internal benches.") - comp_parser.add_argument( - '--no-litmus', - action='store_true', - help="Don't build litmus benches.") + if any(re.fullmatch('-[^-]*[hc].*|--help|--compile', a) for a in sys.argv): + comp_parser.add_argument( + '-o', '--output', + help="Output file.") + comp_parser.add_argument( + '-s', '--source', + help="Source file to compile, possibly injecting internal " + "benches.") + comp_parser.add_argument( + '-i', '--include', + action='append', + help="Inject these header files into every compiled bench " + "file. Defaults to %r." % HEADER_PATHS) + comp_parser.add_argument( + '--no-internal', + action='store_true', + help="Don't build internal benches.") + comp_parser.add_argument( + '--no-litmus', + action='store_true', + help="Don't build litmus benches.") # do the thing args = parser.parse_intermixed_args() + # bench_paths/bench_ids overlap, so need to do some munging args.bench_paths = args.bench_ids sys.exit(main(**{k: v for k, v in vars(args).items() diff --git a/scripts/perf.py b/scripts/perf.py index faf51afb..e1a677cd 100755 --- a/scripts/perf.py +++ b/scripts/perf.py @@ -3,7 +3,7 @@ # Script to aggregate and report Linux perf results. # # Example: -# ./scripts/perf.py --record -obench.perf ./runners/bench_runner +# ./scripts/perf.py -e -obench.perf ./runners/bench_runner # ./scripts/perf.py bench.perf -j -Flfs.c -Flfs_util.c -Scycles # # Copyright (c) 2022, The littlefs authors. @@ -39,7 +39,7 @@ import zipfile PERF_PATH = ['perf'] PERF_EVENTS = 'cycles,branch-misses,branches,cache-misses,cache-references' -PERF_FREQ = 100 +PERF_RUNFREQ = 100 OBJDUMP_PATH = ['objdump'] THRESHOLD = (0.5, 0.85) @@ -202,8 +202,8 @@ def openio(path, mode='r', buffering=-1): # run perf as a subprocess, storing measurements into a zip file def record(command, *, output=None, - perf_freq=PERF_FREQ, - perf_period=None, + perf_step=None, + perf_runfreq=PERF_RUNFREQ, perf_events=PERF_EVENTS, perf_path=PERF_PATH, **args): @@ -213,11 +213,11 @@ def record(command, *, # figure out our perf invocation perf = perf_path + list(filter(None, [ 'record', - '-F%s' % perf_freq - if perf_freq is not None - and perf_period is None else None, - '-c%s' % perf_period - if perf_period is not None else None, + '-c%s' % perf_step + if perf_step is not None else None, + '-F%s' % perf_runfreq + if perf_runfreq is not None + and perf_step is None else None, '-B', '-g', '--all-user', @@ -1660,11 +1660,12 @@ def main(**args): if __name__ == "__main__": import argparse import sys + import re # bit of a hack, but parse_intermixed_args and REMAINDER are # incompatible, so we need to figure out what we want before running # argparse - if '--record' in sys.argv: + if any(re.fullmatch('-[^-]*[e].*|--record', a) for a in sys.argv): nargs = argparse.REMAINDER else: nargs = '*' @@ -1900,29 +1901,30 @@ if __name__ == "__main__": nargs=nargs, help="Command to run.") record_parser.add_argument( - '--record', + '-e', '--record', action='store_true', help="Run a command and aggregate perf measurements.") - record_parser.add_argument( - '-o', '--output', - help="Output file. Uses flock to synchronize. This is stored as a " - "zip-file of multiple perf results.") - record_parser.add_argument( - '--perf-freq', - help="perf sampling frequency. This is passed directly to perf. " - "Defaults to %r." % PERF_FREQ) - record_parser.add_argument( - '--perf-period', - help="perf sampling period. This is passed directly to perf.") - record_parser.add_argument( - '--perf-events', - help="perf events to record. This is passed directly to perf. " - "Defaults to %r." % PERF_EVENTS) - record_parser.add_argument( - '--perf-path', - type=lambda x: x.split(), - help="Path to the perf executable, may include flags. " - "Defaults to %r." % PERF_PATH) + if any(re.fullmatch('-[^-]*[he].*|--help|--record', a) for a in sys.argv): + record_parser.add_argument( + '-o', '--output', + help="Output file. Uses flock to synchronize. This is stored " + "as a zip-file of multiple perf results.") + record_parser.add_argument( + '--perf-step', + help="perf sampling step. This is passed directly to perf.") + record_parser.add_argument( + '--perf-runfreq', + help="perf sampling frequency. This is passed directly to " + "perf. Defaults to %r." % PERF_RUNFREQ) + record_parser.add_argument( + '--perf-events', + help="perf events to record. This is passed directly to " + "perf. Defaults to %r." % PERF_EVENTS) + record_parser.add_argument( + '--perf-path', + type=lambda x: x.split(), + help="Path to the perf executable, may include flags. " + "Defaults to %r." % PERF_PATH) # avoid intermixed/REMAINDER conflict, see above if nargs == argparse.REMAINDER: @@ -1930,7 +1932,7 @@ if __name__ == "__main__": else: args = parser.parse_intermixed_args() - # perf_paths/command overlap, so need to do some munging here + # perf_paths/command overlap, so need to do some munging args.command = args.perf_paths if args.record: if not args.command: diff --git a/scripts/test.py b/scripts/test.py index ce4e80b6..b5d4f4ce 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -805,11 +805,11 @@ def find_runner(runner, id=None, main=True, **args): # run under perf? if args.get('perf'): cmd[:0] = args['perf_script'] + list(filter(None, [ - '--record', - '--perf-freq=%s' % args['perf_freq'] - if args.get('perf_freq') else None, - '--perf-period=%s' % args['perf_period'] - if args.get('perf_period') else None, + '-e', + '--perf-step=%s' % args['perf_step'] + if args.get('perf_step') else None, + '--perf-runfreq=%s' % args['perf_runfreq'] + if args.get('perf_runfreq') else None, '--perf-events=%s' % args['perf_events'] if args.get('perf_events') else None, '--perf-path=%s' % args['perf_path'] @@ -839,10 +839,10 @@ def find_runner(runner, id=None, main=True, **args): cmd.append('-t%s' % args['trace']) if args.get('trace_backtrace'): cmd.append('--trace-backtrace') - if args.get('trace_period'): - cmd.append('--trace-period=%s' % args['trace_period']) - if args.get('trace_freq'): - cmd.append('--trace-freq=%s' % args['trace_freq']) + if args.get('trace_step'): + cmd.append('--trace-step=%s' % args['trace_step']) + if args.get('trace_runfreq'): + cmd.append('--trace-runfreq=%s' % args['trace_runfreq']) if args.get('read_sleep'): cmd.append('--read-sleep=%s' % args['read_sleep']) if args.get('prog_sleep'): @@ -1269,9 +1269,9 @@ def run_stage(name, runner, test_ids, stdout_, trace_, output_, **args): while start < total_perms: runner_ = find_runner(runner, main=main, **args) if args.get('isolate') or args.get('valgrind'): - runner_.append('-s%s,%s,%s' % (start, start+step, step)) + runner_.append('--step=%s,%s,%s' % (start, start+step, step)) elif start != 0 or step != 1: - runner_.append('-s%s,,%s' % (start, step)) + runner_.append('--step=%s,,%s' % (start, step)) runner_.extend(test_ids) @@ -1655,6 +1655,7 @@ def main(**args): if __name__ == "__main__": import argparse import sys + import re argparse.ArgumentParser._handle_conflict_ignore = lambda *_: None argparse._ArgumentGroup._handle_conflict_ignore = lambda *_: None parser = argparse.ArgumentParser( @@ -1760,10 +1761,10 @@ if __name__ == "__main__": action='store_true', help="Include a backtrace with every trace statement.") test_parser.add_argument( - '--trace-period', - help="Sample trace output at this period in cycles.") + '--trace-step', + help="Sample trace output every n steps.") test_parser.add_argument( - '--trace-freq', + '--trace-runfreq', help="Sample trace output at this frequency in hz.") test_parser.add_argument( '-O', '--stdout', @@ -1876,13 +1877,13 @@ if __name__ == "__main__": help="Run under Linux's perf to sample performance counters, " "writing samples to this file.") test_parser.add_argument( - '--perf-freq', + '--perf-step', + help="perf sampling step. This is passed directly to the perf " + "script.") + test_parser.add_argument( + '--perf-runfreq', help="perf sampling frequency. This is passed directly to the " "perf script.") - test_parser.add_argument( - '--perf-period', - help="perf sampling period. This is passed directly to the perf " - "script.") test_parser.add_argument( '--perf-events', help="perf events to record. This is passed directly to the perf " @@ -1909,31 +1910,34 @@ if __name__ == "__main__": '-c', '--compile', action='store_true', help="Compile a test suite or source file.") - comp_parser.add_argument( - '-o', '--output', - help="Output file.") - comp_parser.add_argument( - '-s', '--source', - help="Source file to compile, possibly injecting internal tests.") - comp_parser.add_argument( - '--include', - help="Inject these header files into every compiled test file. " - "Defaults to %r." % HEADER_PATHS) - comp_parser.add_argument( - '--no-internal', - action='store_true', - help="Don't build internal tests.") - comp_parser.add_argument( - '--no-reentrant', - action='store_true', - help="Don't build reentrant tests.") - comp_parser.add_argument( - '--no-fuzz', - action='store_true', - help="Don't build fuzz tests.") + if any(re.fullmatch('-[^-]*[hc].*|--help|--compile', a) for a in sys.argv): + comp_parser.add_argument( + '-o', '--output', + help="Output file.") + comp_parser.add_argument( + '-s', '--source', + help="Source file to compile, possibly injecting internal " + "tests.") + comp_parser.add_argument( + '-i', '--include', + help="Inject these header files into every compiled test " + "file. Defaults to %r." % HEADER_PATHS) + comp_parser.add_argument( + '--no-internal', + action='store_true', + help="Don't build internal tests.") + comp_parser.add_argument( + '--no-reentrant', + action='store_true', + help="Don't build reentrant tests.") + comp_parser.add_argument( + '--no-fuzz', + action='store_true', + help="Don't build fuzz tests.") # do the thing args = parser.parse_intermixed_args() + # test_paths/test_ids overlap, so need to do some munging args.test_paths = args.test_ids sys.exit(main(**{k: v for k, v in vars(args).items()