summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorMichael Droettboom <mdboom@gmail.com>2023-09-12 21:12:57 (GMT)
committerGitHub <noreply@github.com>2023-09-12 21:12:57 (GMT)
commit5dcbbd8861e618488d95416dee8ea94577e3f4f0 (patch)
tree927dd61ea0134f9cada72b1b28d6b592184ee4e4 /Tools
parent90cf345ed42ae4d17d2a073718985eb3432a7c20 (diff)
downloadcpython-5dcbbd8861e618488d95416dee8ea94577e3f4f0.zip
cpython-5dcbbd8861e618488d95416dee8ea94577e3f4f0.tar.gz
cpython-5dcbbd8861e618488d95416dee8ea94577e3f4f0.tar.bz2
GH-109330: Dump and compare stats using opcode names, not numbers (GH-109335)
Diffstat (limited to 'Tools')
-rw-r--r--Tools/scripts/summarize_stats.py72
1 files changed, 27 insertions, 45 deletions
diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py
index 55b6764..484dfe8 100644
--- a/Tools/scripts/summarize_stats.py
+++ b/Tools/scripts/summarize_stats.py
@@ -16,22 +16,6 @@ if os.name == "nt":
else:
DEFAULT_DIR = "/tmp/py_stats/"
-#Create list of all instruction names
-specialized = iter(opcode._specialized_opmap.keys())
-opname = ["<0>"]
-for name in opcode.opname[1:]:
- if name.startswith("<"):
- try:
- name = next(specialized)
- except StopIteration:
- pass
- opname.append(name)
-
-# opcode_name --> opcode
-# Sort alphabetically.
-opmap = {name: i for i, name in enumerate(opname)}
-opmap = dict(sorted(opmap.items()))
-
TOTAL = "specialization.hit", "specialization.miss", "execution_count"
def format_ratio(num, den):
@@ -200,12 +184,12 @@ def gather_stats(input):
raise ValueError(f"{input:r} is not a file or directory path")
def extract_opcode_stats(stats):
- opcode_stats = [ {} for _ in range(256) ]
+ opcode_stats = collections.defaultdict(dict)
for key, value in stats.items():
if not key.startswith("opcode"):
continue
- n, _, rest = key[7:].partition("]")
- opcode_stats[int(n)][rest.strip(".")] = value
+ name, _, rest = key[7:].partition("]")
+ opcode_stats[name][rest.strip(".")] = value
return opcode_stats
def parse_kinds(spec_src, prefix="SPEC_FAIL"):
@@ -246,11 +230,10 @@ def categorized_counts(opcode_stats):
specialized_instructions = {
op for op in opcode._specialized_opmap.keys()
if "__" not in op}
- for i, opcode_stat in enumerate(opcode_stats):
+ for name, opcode_stat in opcode_stats.items():
if "execution_count" not in opcode_stat:
continue
count = opcode_stat['execution_count']
- name = opname[i]
if "specializable" in opcode_stat:
not_specialized += count
elif name in specialized_instructions:
@@ -314,13 +297,13 @@ def emit_table(header, rows):
def calculate_execution_counts(opcode_stats, total):
counts = []
- for i, opcode_stat in enumerate(opcode_stats):
+ for name, opcode_stat in opcode_stats.items():
if "execution_count" in opcode_stat:
count = opcode_stat['execution_count']
miss = 0
if "specializable" not in opcode_stat:
miss = opcode_stat.get("specialization.miss")
- counts.append((count, opname[i], miss))
+ counts.append((count, name, miss))
counts.sort(reverse=True)
cumulative = 0
rows = []
@@ -381,16 +364,17 @@ def get_defines():
def emit_specialization_stats(opcode_stats):
defines = get_defines()
with Section("Specialization stats", summary="specialization stats by family"):
- for i, opcode_stat in enumerate(opcode_stats):
- name = opname[i]
+ for name, opcode_stat in opcode_stats.items():
print_specialization_stats(name, opcode_stat, defines)
def emit_comparative_specialization_stats(base_opcode_stats, head_opcode_stats):
defines = get_defines()
with Section("Specialization stats", summary="specialization stats by family"):
- for i, (base_opcode_stat, head_opcode_stat) in enumerate(zip(base_opcode_stats, head_opcode_stats)):
- name = opname[i]
- print_comparative_specialization_stats(name, base_opcode_stat, head_opcode_stat, defines)
+ opcodes = set(base_opcode_stats.keys()) & set(head_opcode_stats.keys())
+ for opcode in opcodes:
+ print_comparative_specialization_stats(
+ opcode, base_opcode_stats[opcode], head_opcode_stats[opcode], defines
+ )
def calculate_specialization_effectiveness(opcode_stats, total):
basic, not_specialized, specialized = categorized_counts(opcode_stats)
@@ -407,12 +391,12 @@ def emit_specialization_overview(opcode_stats, total):
for title, field in (("Deferred", "specialization.deferred"), ("Misses", "specialization.miss")):
total = 0
counts = []
- for i, opcode_stat in enumerate(opcode_stats):
+ for name, opcode_stat in opcode_stats.items():
# Avoid double counting misses
if title == "Misses" and "specializable" in opcode_stat:
continue
value = opcode_stat.get(field, 0)
- counts.append((value, opname[i]))
+ counts.append((value, name))
total += value
counts.sort(reverse=True)
if total:
@@ -539,29 +523,27 @@ def emit_comparative_gc_stats(base_stats, head_stats):
def get_total(opcode_stats):
total = 0
- for opcode_stat in opcode_stats:
+ for opcode_stat in opcode_stats.values():
if "execution_count" in opcode_stat:
total += opcode_stat['execution_count']
return total
def emit_pair_counts(opcode_stats, total):
pair_counts = []
- for i, opcode_stat in enumerate(opcode_stats):
- if i == 0:
- continue
+ for name_i, opcode_stat in opcode_stats.items():
for key, value in opcode_stat.items():
if key.startswith("pair_count"):
- x, _, _ = key[11:].partition("]")
+ name_j, _, _ = key[11:].partition("]")
if value:
- pair_counts.append((value, (i, int(x))))
+ pair_counts.append((value, (name_i, name_j)))
with Section("Pair counts", summary="Pair counts for top 100 pairs"):
pair_counts.sort(reverse=True)
cumulative = 0
rows = []
for (count, pair) in itertools.islice(pair_counts, 100):
- i, j = pair
+ name_i, name_j = pair
cumulative += count
- rows.append((opname[i] + " " + opname[j], count, format_ratio(count, total),
+ rows.append((f"{name_i} {name_j}", count, format_ratio(count, total),
format_ratio(cumulative, total)))
emit_table(("Pair", "Count:", "Self:", "Cumulative:"),
rows
@@ -577,18 +559,18 @@ def emit_pair_counts(opcode_stats, total):
successors[first][second] = count
total_predecessors[second] += count
total_successors[first] += count
- for name, i in opmap.items():
- total1 = total_predecessors[i]
- total2 = total_successors[i]
+ for name in opcode_stats.keys():
+ total1 = total_predecessors[name]
+ total2 = total_successors[name]
if total1 == 0 and total2 == 0:
continue
pred_rows = succ_rows = ()
if total1:
- pred_rows = [(opname[pred], count, f"{count/total1:.1%}")
- for (pred, count) in predecessors[i].most_common(5)]
+ pred_rows = [(pred, count, f"{count/total1:.1%}")
+ for (pred, count) in predecessors[name].most_common(5)]
if total2:
- succ_rows = [(opname[succ], count, f"{count/total2:.1%}")
- for (succ, count) in successors[i].most_common(5)]
+ succ_rows = [(succ, count, f"{count/total2:.1%}")
+ for (succ, count) in successors[name].most_common(5)]
with Section(name, 3, f"Successors and predecessors for {name}"):
emit_table(("Predecessors", "Count:", "Percentage:"),
pred_rows