mirror of https://github.com/python/cpython
104 lines
3.4 KiB
Python
104 lines
3.4 KiB
Python
"""Print a summary of specialization stats for all files in the
|
|
default stats folders.
|
|
"""
|
|
|
|
import collections
|
|
import os.path
|
|
import opcode
|
|
|
|
if os.name == "nt":
|
|
DEFAULT_DIR = "c:\\temp\\py_stats\\"
|
|
else:
|
|
DEFAULT_DIR = "/tmp/py_stats/"
|
|
|
|
#Create list of all instruction names
|
|
specialized = iter(opcode._specialized_instructions)
|
|
opname = ["<0>"]
|
|
for name in opcode.opname[1:]:
|
|
if name.startswith("<"):
|
|
try:
|
|
name = next(specialized)
|
|
except StopIteration:
|
|
pass
|
|
opname.append(name)
|
|
|
|
|
|
TOTAL = "specialization.deferred", "specialization.hit", "specialization.miss", "execution_count"
|
|
|
|
def print_specialization_stats(name, family_stats):
|
|
if "specialization.deferred" not in family_stats:
|
|
return
|
|
total = sum(family_stats.get(kind, 0) for kind in TOTAL)
|
|
if total == 0:
|
|
return
|
|
print(name+":")
|
|
for key in sorted(family_stats):
|
|
if key.startswith("specialization.failure_kinds"):
|
|
continue
|
|
if key.startswith("specialization."):
|
|
label = key[len("specialization."):]
|
|
elif key == "execution_count":
|
|
label = "unquickened"
|
|
if key not in ("specialization.success", "specialization.failure"):
|
|
print(f"{label:>12}:{family_stats[key]:>12} {100*family_stats[key]/total:0.1f}%")
|
|
for key in ("specialization.success", "specialization.failure"):
|
|
label = key[len("specialization."):]
|
|
print(f" {label}:{family_stats.get(key, 0):>12}")
|
|
total_failures = family_stats.get("specialization.failure", 0)
|
|
failure_kinds = [ 0 ] * 30
|
|
for key in family_stats:
|
|
if not key.startswith("specialization.failure_kind"):
|
|
continue
|
|
_, index = key[:-1].split("[")
|
|
index = int(index)
|
|
failure_kinds[index] = family_stats[key]
|
|
for index, value in enumerate(failure_kinds):
|
|
if not value:
|
|
continue
|
|
print(f" kind {index:>2}: {value:>8} {100*value/total_failures:0.1f}%")
|
|
|
|
def gather_stats():
|
|
stats = collections.Counter()
|
|
for filename in os.listdir(DEFAULT_DIR):
|
|
with open(os.path.join(DEFAULT_DIR, filename)) as fd:
|
|
for line in fd:
|
|
key, value = line.split(":")
|
|
key = key.strip()
|
|
value = int(value.strip())
|
|
stats[key] += value
|
|
return stats
|
|
|
|
def extract_opcode_stats(stats):
|
|
opcode_stats = [ {} for _ in range(256) ]
|
|
for key, value in stats.items():
|
|
if not key.startswith("opcode"):
|
|
continue
|
|
n, _, rest = key[7:].partition("]")
|
|
opcode_stats[int(n)][rest.strip(".")] = value
|
|
return opcode_stats
|
|
|
|
|
|
def main():
|
|
stats = gather_stats()
|
|
opcode_stats = extract_opcode_stats(stats)
|
|
print("Execution counts:")
|
|
counts = []
|
|
total = 0
|
|
for i, opcode_stat in enumerate(opcode_stats):
|
|
if "execution_count" in opcode_stat:
|
|
count = opcode_stat['execution_count']
|
|
counts.append((count, opname[i]))
|
|
total += count
|
|
counts.sort(reverse=True)
|
|
cummulative = 0
|
|
for (count, name) in counts:
|
|
cummulative += count
|
|
print(f"{name}: {count} {100*count/total:0.1f}% {100*cummulative/total:0.1f}%")
|
|
print("Specialization stats:")
|
|
for i, opcode_stat in enumerate(opcode_stats):
|
|
name = opname[i]
|
|
print_specialization_stats(name, opcode_stat)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|