|
4 | 4 | import re
|
5 | 5 | import sys
|
6 | 6 | from itertools import chain
|
7 |
| -from typing import Iterable, List |
| 7 | +from typing import Callable, Iterable, List, Pattern, Tuple |
8 | 8 |
|
9 | 9 | import analyze
|
10 | 10 | from analyze import Block, ioutils, utils
|
|
14 | 14 | '''
|
15 | 15 |
|
16 | 16 | _RE_OCCUPANCY = re.compile(r'Final occupancy for function (?P<name>\S+):(?P<value>\d+)')
|
| 17 | +_RE_SPILLS = re.compile(r'Function: (?P<name>\S*?)\nGREEDY RA: Number of spilled live ranges: (?P<value>\d+)') |
| 18 | +_RE_SPILLS_WEIGHTED = re.compile(r'SC in Function (?P<name>\S*?) (?P<value>-?\d+)') |
17 | 19 |
|
18 | 20 |
|
19 |
| -def _occupancy_info_in_block_log(block: Block) -> Iterable[int]: |
20 |
| - for m in _RE_OCCUPANCY.finditer(block.raw_log): |
21 |
| - yield int(m['value']) |
| 21 | +def compute_avg_values(fn_info: List[Tuple[str, int]], *, fn_filter: Callable[[str, int], bool] = lambda k, v: True) -> float: |
| 22 | + return utils.average((v for k, v in fn_info if fn_filter(k, v)), len(fn_info)) |
22 | 23 |
|
23 | 24 |
|
24 |
| -def function_occupancy_info(logs: Iterable[Block]) -> List[int]: |
25 |
| - return list(chain.from_iterable(map(_occupancy_info_in_block_log, logs))) |
| 25 | +def _fn_re_info(re: Pattern, logs: Iterable[Block], key='name', value='value') -> Iterable[Tuple[str, int]]: |
| 26 | + for m in chain.from_iterable(re.finditer(blk.raw_log) for blk in logs): |
| 27 | + yield (m[key], int(m[value])) |
26 | 28 |
|
27 | 29 |
|
28 |
| -def avg_occupancy(logs: Iterable[Block]) -> float: |
29 |
| - occ_info = function_occupancy_info(logs) |
30 |
| - return sum(occ_info) / len(occ_info) if occ_info else 0.0 |
| 30 | +def fn_occupancy_info(logs: Iterable[Block]) -> List[Tuple[str, int]]: |
| 31 | + return list(_fn_re_info(_RE_OCCUPANCY, logs)) |
| 32 | + |
| 33 | + |
| 34 | +def avg_occupancy(logs: Iterable[Block], *, fn_filter: Callable[[str, int], bool] = lambda k, v: True) -> float: |
| 35 | + occ_info = fn_occupancy_info(logs) |
| 36 | + return compute_avg_values(occ_info, fn_filter=fn_filter) |
| 37 | + |
| 38 | + |
| 39 | +def fn_spill_info(logs: Iterable[Block]) -> List[Tuple[str, int]]: |
| 40 | + return list(_fn_re_info(_RE_SPILLS, logs)) |
| 41 | + |
| 42 | + |
| 43 | +def fn_weighted_spill_info(logs: Iterable[Block]) -> List[Tuple[str, int]]: |
| 44 | + return list(_fn_re_info(_RE_SPILLS_WEIGHTED, logs)) |
| 45 | + |
| 46 | + |
| 47 | +def total_spills(logs: Iterable[Block], *, fn_filter: Callable[[str, int], bool] = lambda k, v: True) -> int: |
| 48 | + return sum(v for k, v in fn_spill_info(logs) if fn_filter(k, v)) |
| 49 | + |
| 50 | + |
| 51 | +def total_weighted_spills(logs: Iterable[Block], *, fn_filter: Callable[[str, int], bool] = lambda k, v: True) -> int: |
| 52 | + return sum(v for k, v in fn_weighted_spill_info(logs) if fn_filter(k, v)) |
31 | 53 |
|
32 | 54 |
|
33 | 55 | def raw_main(argv: List[str] = []):
|
34 | 56 | parser = argparse.ArgumentParser(
|
35 | 57 | description='Computes the block stats for the logs')
|
36 |
| - parser.add_argument('--stat', required=True, choices=('occ',), |
| 58 | + parser.add_argument('--stat', required=True, choices=('occ', 'spills', 'weighted-spills'), |
37 | 59 | help='Which stat to compute')
|
38 |
| - parser.add_argument('logs', help='The logs to analyze') |
| 60 | + parser.add_argument('--hot-only', help='A file with a space-separated list of functions to consider in the count') |
39 | 61 | ioutils.add_output_format_arg(parser)
|
40 |
| - args = analyze.parse_args(parser, 'logs') |
| 62 | + parser.add_argument('logs', help='The logs to analyze') |
| 63 | + args = analyze.parse_args(parser, 'logs', args=argv) |
| 64 | + |
| 65 | + if args.hot_only: |
| 66 | + with open(args.hot_only, 'r') as f: |
| 67 | + contents = f.read() |
| 68 | + fns = set(contents.split()) |
| 69 | + def fn_filter(k, v): return k in fns |
| 70 | + else: |
| 71 | + def fn_filter(k, v): return True |
41 | 72 |
|
42 | 73 | STATS = {
|
43 | 74 | 'occ': ('Average Occupancy', avg_occupancy),
|
| 75 | + 'spills': ('Spill Count', total_spills), |
| 76 | + 'weighted-spills': ('Weighted Spill Count', total_weighted_spills), |
44 | 77 | }
|
45 | 78 | label, f = STATS[args.stat]
|
46 | 79 |
|
47 |
| - results = utils.foreach_bench(lambda bench: {label: f(bench)}, args.logs) |
| 80 | + results = utils.foreach_bench(lambda bench: {label: f(bench, fn_filter=fn_filter)}, args.logs) |
48 | 81 |
|
49 | 82 | args.format(sys.stdout, results)
|
50 | 83 |
|
51 | 84 |
|
52 | 85 | if __name__ == '__main__':
|
53 |
| - raw_main(sys.argv) |
| 86 | + raw_main(None) # Default to sys.argv |
0 commit comments