import json
import os
import sys
def default_criterion_dir():
return os.path.join(os.environ.get("CARGO_TARGET_DIR", "target"), "criterion")
def get_criterion_results(target_dir=None):
if target_dir is None:
target_dir = default_criterion_dir()
results = {}
if not os.path.isdir(target_dir):
return results
for root, dirs, files in os.walk(target_dir):
if "report" in dirs:
dirs.remove("report")
if os.path.basename(root) == "new" and "estimates.json" in files:
estimates_path = os.path.join(root, "estimates.json")
bench_dir = os.path.dirname(root) bench_id = os.path.relpath(bench_dir, target_dir).replace(os.sep, "_")
with open(estimates_path) as f:
estimates = json.load(f)
mean = estimates["mean"]
results[bench_id] = {
"mean_ns": mean["point_estimate"],
"cilower": mean["confidence_interval"]["lower_bound"],
"ciupper": mean["confidence_interval"]["upper_bound"],
}
return results
def get_table_bench_results(target_dir=None, group="table"):
if target_dir is None:
target_dir = default_criterion_dir()
results = []
group_dir = os.path.join(target_dir, group)
all_results = get_criterion_results(group_dir)
op_types = ["read_b", "read_ub", "write"]
def _parse_config(config_str):
if "::" in config_str:
parts = config_str.split("::")
else:
parts = config_str.split("__")
if len(parts) == 3:
use_table = parts[2] == "Table"
return parts[0], parts[1], use_table
return None
for bench_id, stats in all_results.items():
config_str = None
op = None
for op_type in op_types:
suffix = "_" + op_type
if bench_id.endswith(suffix):
config_str = bench_id[: -len(suffix)]
op = op_type
break
if config_str is None:
parts = bench_id.rsplit("/", 1)
if len(parts) == 2:
config_str, op = parts[0], parts[1]
if config_str is None:
continue
parsed = _parse_config(config_str)
if parsed is None:
continue
code, endian, use_table = parsed
results.append(
{
"code": code,
"endian": endian,
"use_table": use_table,
"op": op,
"mean_ns": stats["mean_ns"],
"cilower": stats["cilower"],
"ciupper": stats["ciupper"],
}
)
return results
def get_comp_bench_results(target_dir=None):
if target_dir is None:
target_dir = default_criterion_dir()
results = []
group_dir = os.path.join(target_dir, "comparative")
all_results = get_criterion_results(group_dir)
for bench_id, stats in all_results.items():
parts = bench_id.split("/")
if len(parts) == 4:
code, endian, dist, op = parts
if (
op not in ("read", "write")
or dist not in ("implied", "univ")
or endian not in ("BE", "LE")
):
continue
else:
parts = bench_id.split("_")
if len(parts) < 4:
continue
op = parts[-1]
dist = parts[-2]
endian = parts[-3]
code = "_".join(parts[:-3])
if op not in ("read", "write"):
continue
if dist not in ("implied", "univ"):
continue
if endian not in ("BE", "LE"):
continue
results.append(
{
"code": code,
"op": op,
"dist": dist,
"endian": endian,
"mean_ns": stats["mean_ns"],
"cilower": stats["cilower"],
"ciupper": stats["ciupper"],
}
)
return results
def parse_ratios_from_stderr(stderr_text):
ratios = {}
for line in stderr_text.splitlines():
if line.startswith("RATIO:"):
parts = line[6:].split(",")
if len(parts) == 2:
key_parts = parts[0].split("::")
if len(key_parts) == 3:
use_table = key_parts[2] == "Table"
ratios[(key_parts[0], key_parts[1], use_table)] = float(parts[1])
return ratios