Skip to content

Commit 208fa9f

Browse files
committed
Add spill func-level info functions
1 parent da627e1 commit 208fa9f

File tree

2 files changed

+64
-14
lines changed

2 files changed

+64
-14
lines changed

util/analyze/lib/func_stats.py

+47-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
import sys
66
from itertools import chain
7-
from typing import Iterable, List
7+
from typing import Callable, Iterable, List, Pattern, Tuple
88

99
import analyze
1010
from analyze import Block, ioutils, utils
@@ -14,40 +14,73 @@
1414
'''
1515

1616
_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+)')
1719

1820

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))
2223

2324

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]))
2628

2729

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))
3153

3254

3355
def raw_main(argv: List[str] = []):
3456
parser = argparse.ArgumentParser(
3557
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'),
3759
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')
3961
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
4172

4273
STATS = {
4374
'occ': ('Average Occupancy', avg_occupancy),
75+
'spills': ('Spill Count', total_spills),
76+
'weighted-spills': ('Weighted Spill Count', total_weighted_spills),
4477
}
4578
label, f = STATS[args.stat]
4679

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)
4881

4982
args.format(sys.stdout, results)
5083

5184

5285
if __name__ == '__main__':
53-
raw_main(sys.argv)
86+
raw_main(None) # Default to sys.argv

util/analyze/utils.py

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Iterable
12
from ._types import *
23

34

@@ -77,6 +78,7 @@ def zipped_keep_blocks_if(*logs, pred):
7778
except StopIteration:
7879
# There was nothing in zip(*logs)...
7980
old_pred = pred
81+
8082
def new_pred(*blks):
8183
try:
8284
return old_pred(*blks)
@@ -111,3 +113,18 @@ def zip_benchmarks_if(*benchmarks):
111113

112114
def sum_stat_for_all(stat, logs: Logs) -> int:
113115
return sum(stat(blk) for blk in logs)
116+
117+
118+
def average(xs: Iterable[int], count=None) -> float:
119+
try:
120+
size = count if count is not None else len(xs)
121+
return sum(xs) / size if size else 0.0
122+
except TypeError:
123+
pass
124+
125+
acc = 0
126+
num = 0
127+
for x in xs:
128+
acc += x
129+
num += 1
130+
return acc / num if num else 0.0

0 commit comments

Comments
 (0)