chore: import upstream snapshot with attribution
bazel / bazel.ubuntu-latest (push) Failing after 1s
build-and-test-perfcounters / ubuntu-latest.Debug (push) Failing after 0s
build-and-test-perfcounters / ubuntu-latest.Release (push) Failing after 1s
doxygen / Build HTML documentation (push) Failing after 1s
python + Bazel pre-commit checks / pre-commit (push) Failing after 1s
sanitizer / tsan.Debug (push) Failing after 1s
sanitizer / ubsan.Debug (push) Failing after 0s
sanitizer / ubsan.RelWithDebInfo (push) Failing after 1s
build-and-test-min-cmake / ubuntu-latest.min-cmake (push) Failing after 1s
clang-format-lint / check-clang-format (push) Failing after 1s
sanitizer / asan.Debug (push) Failing after 1s
sanitizer / msan.RelWithDebInfo (push) Failing after 1s
clang-tidy / run-clang-tidy (push) Failing after 1s
sanitizer / msan.Debug (push) Failing after 1s
sanitizer / asan.RelWithDebInfo (push) Failing after 0s
sanitizer / tsan.RelWithDebInfo (push) Failing after 0s
test-bindings / Test Rust bindings on ubuntu-latest (push) Failing after 0s
test-bindings / Test Python 3.10 bindings on ubuntu-latest (push) Failing after 0s
test-bindings / Test Python 3.11 bindings on ubuntu-latest (push) Failing after 0s
test-bindings / Test Python 3.12 bindings on ubuntu-latest (push) Failing after 1s
test-bindings / Test Python 3.13 bindings on ubuntu-latest (push) Failing after 0s
build-and-test / macos-latest.Debug.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.shared.clang++ (push) Has been cancelled
bazel / bazel.macos-latest (push) Has been cancelled
bazel / bazel.windows-latest (push) Has been cancelled
build-and-test-min-cmake / macos-latest.min-cmake (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Debug.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.shared.g++ (push) Has been cancelled
build-and-test / macos-latest.Debug.static.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.static.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.static.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.static.g++ (push) Has been cancelled
build-and-test / macos-latest.Release.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.shared.clang++ (push) Has been cancelled
build-and-test / macos-latest.Release.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Debug.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Release.static.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.static.g++ (push) Has been cancelled
build-and-test / windows-2025.Debug.static.VS-18-2025 (push) Has been cancelled
build-and-test / windows-2022.Release.shared.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2022.Release.static.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2025.Release.shared.VS-18-2025 (push) Has been cancelled
build-and-test / windows-2025.Release.static.VS-18-2025 (push) Has been cancelled
build-and-test / windows-latest.Debug.shared.CLANG64 (push) Has been cancelled
build-and-test / windows-latest.Debug.shared.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Debug.shared.UCRT64 (push) Has been cancelled
build-and-test / windows-latest.Debug.static.CLANG64 (push) Has been cancelled
build-and-test / windows-latest.Debug.static.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Debug.static.UCRT64 (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.static.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.static.g++ (push) Has been cancelled
build-and-test / windows-2022.Debug.shared.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2022.Debug.static.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2025.Debug.shared.VS-18-2025 (push) Has been cancelled
build-and-test / windows-latest.Release.static.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Release.static.UCRT64 (push) Has been cancelled
test-bindings / Test Python 3.10 bindings on macos-latest (push) Has been cancelled
test-bindings / Test Python 3.11 bindings on macos-latest (push) Has been cancelled
test-bindings / Test Python 3.12 bindings on macos-latest (push) Has been cancelled
test-bindings / Test Python 3.13 bindings on macos-latest (push) Has been cancelled
build-and-test / windows-latest.Release.shared.CLANG64 (push) Has been cancelled
build-and-test / windows-latest.Release.shared.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Release.shared.UCRT64 (push) Has been cancelled
build-and-test / windows-latest.Release.static.CLANG64 (push) Has been cancelled
test-bindings / Test Python 3.12 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Python 3.13 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Python 3.10 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Python 3.11 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Rust bindings on macos-latest (push) Has been cancelled
test-bindings / Test Rust bindings on windows-latest (push) Has been cancelled
bazel / bazel.ubuntu-latest (push) Failing after 1s
build-and-test-perfcounters / ubuntu-latest.Debug (push) Failing after 0s
build-and-test-perfcounters / ubuntu-latest.Release (push) Failing after 1s
doxygen / Build HTML documentation (push) Failing after 1s
python + Bazel pre-commit checks / pre-commit (push) Failing after 1s
sanitizer / tsan.Debug (push) Failing after 1s
sanitizer / ubsan.Debug (push) Failing after 0s
sanitizer / ubsan.RelWithDebInfo (push) Failing after 1s
build-and-test-min-cmake / ubuntu-latest.min-cmake (push) Failing after 1s
clang-format-lint / check-clang-format (push) Failing after 1s
sanitizer / asan.Debug (push) Failing after 1s
sanitizer / msan.RelWithDebInfo (push) Failing after 1s
clang-tidy / run-clang-tidy (push) Failing after 1s
sanitizer / msan.Debug (push) Failing after 1s
sanitizer / asan.RelWithDebInfo (push) Failing after 0s
sanitizer / tsan.RelWithDebInfo (push) Failing after 0s
test-bindings / Test Rust bindings on ubuntu-latest (push) Failing after 0s
test-bindings / Test Python 3.10 bindings on ubuntu-latest (push) Failing after 0s
test-bindings / Test Python 3.11 bindings on ubuntu-latest (push) Failing after 0s
test-bindings / Test Python 3.12 bindings on ubuntu-latest (push) Failing after 1s
test-bindings / Test Python 3.13 bindings on ubuntu-latest (push) Failing after 0s
build-and-test / macos-latest.Debug.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.shared.clang++ (push) Has been cancelled
bazel / bazel.macos-latest (push) Has been cancelled
bazel / bazel.windows-latest (push) Has been cancelled
build-and-test-min-cmake / macos-latest.min-cmake (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Debug.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.shared.g++ (push) Has been cancelled
build-and-test / macos-latest.Debug.static.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Debug.static.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.static.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.static.g++ (push) Has been cancelled
build-and-test / macos-latest.Release.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.shared.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.shared.clang++ (push) Has been cancelled
build-and-test / macos-latest.Release.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Debug.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Debug.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Debug.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Release.static.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.static.g++ (push) Has been cancelled
build-and-test / windows-2025.Debug.static.VS-18-2025 (push) Has been cancelled
build-and-test / windows-2022.Release.shared.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2022.Release.static.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2025.Release.shared.VS-18-2025 (push) Has been cancelled
build-and-test / windows-2025.Release.static.VS-18-2025 (push) Has been cancelled
build-and-test / windows-latest.Debug.shared.CLANG64 (push) Has been cancelled
build-and-test / windows-latest.Debug.shared.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Debug.shared.UCRT64 (push) Has been cancelled
build-and-test / windows-latest.Debug.static.CLANG64 (push) Has been cancelled
build-and-test / windows-latest.Debug.static.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Debug.static.UCRT64 (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.static.clang++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.static.clang++ (push) Has been cancelled
build-and-test / macos-latest.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-22.04.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.shared.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04.Release.static.g++ (push) Has been cancelled
build-and-test / ubuntu-24.04-arm.Release.static.g++ (push) Has been cancelled
build-and-test / windows-2022.Debug.shared.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2022.Debug.static.VS-17-2022 (push) Has been cancelled
build-and-test / windows-2025.Debug.shared.VS-18-2025 (push) Has been cancelled
build-and-test / windows-latest.Release.static.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Release.static.UCRT64 (push) Has been cancelled
test-bindings / Test Python 3.10 bindings on macos-latest (push) Has been cancelled
test-bindings / Test Python 3.11 bindings on macos-latest (push) Has been cancelled
test-bindings / Test Python 3.12 bindings on macos-latest (push) Has been cancelled
test-bindings / Test Python 3.13 bindings on macos-latest (push) Has been cancelled
build-and-test / windows-latest.Release.shared.CLANG64 (push) Has been cancelled
build-and-test / windows-latest.Release.shared.MINGW64 (push) Has been cancelled
build-and-test / windows-latest.Release.shared.UCRT64 (push) Has been cancelled
build-and-test / windows-latest.Release.static.CLANG64 (push) Has been cancelled
test-bindings / Test Python 3.12 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Python 3.13 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Python 3.10 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Python 3.11 bindings on windows-latest (push) Has been cancelled
test-bindings / Test Rust bindings on macos-latest (push) Has been cancelled
test-bindings / Test Rust bindings on windows-latest (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
load("@rules_python//python:defs.bzl", "py_binary", "py_library")
|
||||
load("@tools_pip_deps//:requirements.bzl", "requirement")
|
||||
|
||||
py_library(
|
||||
name = "gbench",
|
||||
srcs = glob(["gbench/*.py"]),
|
||||
deps = [
|
||||
requirement("numpy"),
|
||||
requirement("scipy"),
|
||||
],
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "compare",
|
||||
srcs = ["compare.py"],
|
||||
imports = ["."],
|
||||
python_version = "PY3",
|
||||
deps = [
|
||||
":gbench",
|
||||
],
|
||||
)
|
||||
Executable
+544
@@ -0,0 +1,544 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# type: ignore
|
||||
|
||||
"""
|
||||
compare.py - versatile benchmark output compare tool
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from argparse import ArgumentParser
|
||||
|
||||
import gbench
|
||||
from gbench import report, util
|
||||
|
||||
|
||||
def check_inputs(in1, in2, flags):
|
||||
"""
|
||||
Perform checking on the user provided inputs and diagnose any abnormalities
|
||||
"""
|
||||
in1_kind, _ = util.classify_input_file(in1)
|
||||
in2_kind, _ = util.classify_input_file(in2)
|
||||
output_file = util.find_benchmark_flag("--benchmark_out=", flags)
|
||||
output_type = util.find_benchmark_flag("--benchmark_out_format=", flags)
|
||||
if (
|
||||
in1_kind == util.IT_Executable
|
||||
and in2_kind == util.IT_Executable
|
||||
and output_file
|
||||
):
|
||||
print(
|
||||
(
|
||||
"WARNING: '--benchmark_out=%s' will be passed to both "
|
||||
"benchmarks causing it to be overwritten"
|
||||
)
|
||||
% output_file
|
||||
)
|
||||
if in1_kind == util.IT_JSON and in2_kind == util.IT_JSON:
|
||||
# When both sides are JSON the only supported flag is
|
||||
# --benchmark_filter=
|
||||
for flag in util.remove_benchmark_flags("--benchmark_filter=", flags):
|
||||
print(
|
||||
"WARNING: passing %s has no effect since both "
|
||||
"inputs are JSON" % flag
|
||||
)
|
||||
if output_type is not None and output_type != "json":
|
||||
print(
|
||||
(
|
||||
"ERROR: passing '--benchmark_out_format=%s' to 'compare.py`"
|
||||
" is not supported."
|
||||
)
|
||||
% output_type
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def create_parser():
|
||||
parser = ArgumentParser(
|
||||
description="versatile benchmark output compare tool"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--display_aggregates_only",
|
||||
dest="display_aggregates_only",
|
||||
action="store_true",
|
||||
help="If there are repetitions, by default, we display everything - the"
|
||||
" actual runs, and the aggregates computed. Sometimes, it is "
|
||||
"desirable to only view the aggregates. E.g. when there are a lot "
|
||||
"of repetitions. Do note that only the display is affected. "
|
||||
"Internally, all the actual runs are still used, e.g. for U test.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--no-color",
|
||||
dest="color",
|
||||
default=True,
|
||||
action="store_false",
|
||||
help="Do not use colors in the terminal output",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--dump_to_json",
|
||||
dest="dump_to_json",
|
||||
help=(
|
||||
"Additionally, dump benchmark comparison output to this file in"
|
||||
" JSON format."
|
||||
),
|
||||
)
|
||||
|
||||
utest = parser.add_argument_group()
|
||||
utest.add_argument(
|
||||
"--no-utest",
|
||||
dest="utest",
|
||||
default=True,
|
||||
action="store_false",
|
||||
help=(
|
||||
"The tool can do a two-tailed Mann-Whitney U test with the null"
|
||||
" hypothesis that it is equally likely that a randomly selected"
|
||||
" value from one sample will be less than or greater than a"
|
||||
" randomly selected value from a second sample.\nWARNING: requires"
|
||||
f" **LARGE** (no less than {report.UTEST_OPTIMAL_REPETITIONS})"
|
||||
" number of repetitions to be meaningful!\nThe test is being done"
|
||||
f" by default, if at least {report.UTEST_MIN_REPETITIONS}"
|
||||
" repetitions were done.\nThis option can disable the U Test."
|
||||
),
|
||||
)
|
||||
alpha_default = 0.05
|
||||
utest.add_argument(
|
||||
"--alpha",
|
||||
dest="utest_alpha",
|
||||
default=alpha_default,
|
||||
type=float,
|
||||
help=(
|
||||
"significance level alpha. if the calculated p-value is below this"
|
||||
" value, then the result is said to be statistically significant"
|
||||
" and the null hypothesis is rejected.\n(default: %0.4f)"
|
||||
)
|
||||
% alpha_default,
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(
|
||||
help="This tool has multiple modes of operation:", dest="mode"
|
||||
)
|
||||
|
||||
parser_a = subparsers.add_parser(
|
||||
"benchmarks",
|
||||
help=(
|
||||
"The most simple use-case, compare all the output of these two"
|
||||
" benchmarks"
|
||||
),
|
||||
)
|
||||
baseline = parser_a.add_argument_group("baseline", "The benchmark baseline")
|
||||
baseline.add_argument(
|
||||
"test_baseline",
|
||||
metavar="test_baseline",
|
||||
type=argparse.FileType("r"),
|
||||
nargs=1,
|
||||
help="A benchmark executable or JSON output file",
|
||||
)
|
||||
contender = parser_a.add_argument_group(
|
||||
"contender", "The benchmark that will be compared against the baseline"
|
||||
)
|
||||
contender.add_argument(
|
||||
"test_contender",
|
||||
metavar="test_contender",
|
||||
type=argparse.FileType("r"),
|
||||
nargs=1,
|
||||
help="A benchmark executable or JSON output file",
|
||||
)
|
||||
parser_a.add_argument(
|
||||
"benchmark_options",
|
||||
metavar="benchmark_options",
|
||||
nargs=argparse.REMAINDER,
|
||||
help="Arguments to pass when running benchmark executables",
|
||||
)
|
||||
|
||||
parser_b = subparsers.add_parser(
|
||||
"filters", help="Compare filter one with the filter two of benchmark"
|
||||
)
|
||||
baseline = parser_b.add_argument_group("baseline", "The benchmark baseline")
|
||||
baseline.add_argument(
|
||||
"test",
|
||||
metavar="test",
|
||||
type=argparse.FileType("r"),
|
||||
nargs=1,
|
||||
help="A benchmark executable or JSON output file",
|
||||
)
|
||||
baseline.add_argument(
|
||||
"filter_baseline",
|
||||
metavar="filter_baseline",
|
||||
type=str,
|
||||
nargs=1,
|
||||
help="The first filter, that will be used as baseline",
|
||||
)
|
||||
contender = parser_b.add_argument_group(
|
||||
"contender", "The benchmark that will be compared against the baseline"
|
||||
)
|
||||
contender.add_argument(
|
||||
"filter_contender",
|
||||
metavar="filter_contender",
|
||||
type=str,
|
||||
nargs=1,
|
||||
help="The second filter, that will be compared against the baseline",
|
||||
)
|
||||
parser_b.add_argument(
|
||||
"benchmark_options",
|
||||
metavar="benchmark_options",
|
||||
nargs=argparse.REMAINDER,
|
||||
help="Arguments to pass when running benchmark executables",
|
||||
)
|
||||
|
||||
parser_c = subparsers.add_parser(
|
||||
"benchmarksfiltered",
|
||||
help=(
|
||||
"Compare filter one of first benchmark with filter two of the"
|
||||
" second benchmark"
|
||||
),
|
||||
)
|
||||
baseline = parser_c.add_argument_group("baseline", "The benchmark baseline")
|
||||
baseline.add_argument(
|
||||
"test_baseline",
|
||||
metavar="test_baseline",
|
||||
type=argparse.FileType("r"),
|
||||
nargs=1,
|
||||
help="A benchmark executable or JSON output file",
|
||||
)
|
||||
baseline.add_argument(
|
||||
"filter_baseline",
|
||||
metavar="filter_baseline",
|
||||
type=str,
|
||||
nargs=1,
|
||||
help="The first filter, that will be used as baseline",
|
||||
)
|
||||
contender = parser_c.add_argument_group(
|
||||
"contender", "The benchmark that will be compared against the baseline"
|
||||
)
|
||||
contender.add_argument(
|
||||
"test_contender",
|
||||
metavar="test_contender",
|
||||
type=argparse.FileType("r"),
|
||||
nargs=1,
|
||||
help=(
|
||||
"The second benchmark executable or JSON output file, that will be"
|
||||
" compared against the baseline"
|
||||
),
|
||||
)
|
||||
contender.add_argument(
|
||||
"filter_contender",
|
||||
metavar="filter_contender",
|
||||
type=str,
|
||||
nargs=1,
|
||||
help="The second filter, that will be compared against the baseline",
|
||||
)
|
||||
parser_c.add_argument(
|
||||
"benchmark_options",
|
||||
metavar="benchmark_options",
|
||||
nargs=argparse.REMAINDER,
|
||||
help="Arguments to pass when running benchmark executables",
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
# Parse the command line flags
|
||||
parser = create_parser()
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
if args.mode is None:
|
||||
parser.print_help()
|
||||
exit(1)
|
||||
assert not unknown_args
|
||||
benchmark_options = args.benchmark_options
|
||||
|
||||
if args.mode == "benchmarks":
|
||||
test_baseline = args.test_baseline[0].name
|
||||
test_contender = args.test_contender[0].name
|
||||
filter_baseline = ""
|
||||
filter_contender = ""
|
||||
|
||||
# NOTE: if test_baseline == test_contender, you are analyzing the stdev
|
||||
|
||||
description = "Comparing %s to %s" % (test_baseline, test_contender)
|
||||
elif args.mode == "filters":
|
||||
test_baseline = args.test[0].name
|
||||
test_contender = args.test[0].name
|
||||
filter_baseline = args.filter_baseline[0]
|
||||
filter_contender = args.filter_contender[0]
|
||||
|
||||
# NOTE: if filter_baseline == filter_contender, you are analyzing the
|
||||
# stdev
|
||||
|
||||
description = "Comparing %s to %s (from %s)" % (
|
||||
filter_baseline,
|
||||
filter_contender,
|
||||
args.test[0].name,
|
||||
)
|
||||
elif args.mode == "benchmarksfiltered":
|
||||
test_baseline = args.test_baseline[0].name
|
||||
test_contender = args.test_contender[0].name
|
||||
filter_baseline = args.filter_baseline[0]
|
||||
filter_contender = args.filter_contender[0]
|
||||
|
||||
# NOTE: if test_baseline == test_contender and
|
||||
# filter_baseline == filter_contender, you are analyzing the stdev
|
||||
|
||||
description = "Comparing %s (from %s) to %s (from %s)" % (
|
||||
filter_baseline,
|
||||
test_baseline,
|
||||
filter_contender,
|
||||
test_contender,
|
||||
)
|
||||
else:
|
||||
# should never happen
|
||||
print("Unrecognized mode of operation: '%s'" % args.mode)
|
||||
parser.print_help()
|
||||
exit(1)
|
||||
|
||||
check_inputs(test_baseline, test_contender, benchmark_options)
|
||||
|
||||
if args.display_aggregates_only:
|
||||
benchmark_options += ["--benchmark_display_aggregates_only=true"]
|
||||
|
||||
options_baseline = []
|
||||
options_contender = []
|
||||
|
||||
if filter_baseline and filter_contender:
|
||||
options_baseline = ["--benchmark_filter=%s" % filter_baseline]
|
||||
options_contender = ["--benchmark_filter=%s" % filter_contender]
|
||||
|
||||
# Run the benchmarks and report the results
|
||||
json1 = json1_orig = gbench.util.sort_benchmark_results(
|
||||
gbench.util.run_or_load_benchmark(
|
||||
test_baseline, benchmark_options + options_baseline
|
||||
)
|
||||
)
|
||||
json2 = json2_orig = gbench.util.sort_benchmark_results(
|
||||
gbench.util.run_or_load_benchmark(
|
||||
test_contender, benchmark_options + options_contender
|
||||
)
|
||||
)
|
||||
|
||||
# Now, filter the benchmarks so that the difference report can work
|
||||
if filter_baseline and filter_contender:
|
||||
replacement = "[%s vs. %s]" % (filter_baseline, filter_contender)
|
||||
json1 = gbench.report.filter_benchmark(
|
||||
json1_orig, filter_baseline, replacement
|
||||
)
|
||||
json2 = gbench.report.filter_benchmark(
|
||||
json2_orig, filter_contender, replacement
|
||||
)
|
||||
|
||||
diff_report = gbench.report.get_difference_report(json1, json2, args.utest)
|
||||
output_lines = gbench.report.print_difference_report(
|
||||
diff_report,
|
||||
args.display_aggregates_only,
|
||||
args.utest,
|
||||
args.utest_alpha,
|
||||
args.color,
|
||||
)
|
||||
print(description)
|
||||
for ln in output_lines:
|
||||
print(ln)
|
||||
|
||||
# Optionally, diff and output to JSON
|
||||
if args.dump_to_json is not None:
|
||||
with open(args.dump_to_json, "w") as f_json:
|
||||
json.dump(diff_report, f_json, indent=1)
|
||||
|
||||
|
||||
class TestParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.parser = create_parser()
|
||||
testInputs = os.path.join(
|
||||
os.path.dirname(os.path.realpath(__file__)), "gbench", "Inputs"
|
||||
)
|
||||
self.testInput0 = os.path.join(testInputs, "test1_run1.json")
|
||||
self.testInput1 = os.path.join(testInputs, "test1_run2.json")
|
||||
|
||||
def test_benchmarks_basic(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["benchmarks", self.testInput0, self.testInput1]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_benchmarks_basic_without_utest(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["--no-utest", "benchmarks", self.testInput0, self.testInput1]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertFalse(parsed.utest)
|
||||
self.assertEqual(parsed.utest_alpha, 0.05)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_benchmarks_basic_display_aggregates_only(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["-a", "benchmarks", self.testInput0, self.testInput1]
|
||||
)
|
||||
self.assertTrue(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_benchmarks_basic_with_utest_alpha(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["--alpha=0.314", "benchmarks", self.testInput0, self.testInput1]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.utest_alpha, 0.314)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_benchmarks_basic_without_utest_with_utest_alpha(self):
|
||||
parsed = self.parser.parse_args(
|
||||
[
|
||||
"--no-utest",
|
||||
"--alpha=0.314",
|
||||
"benchmarks",
|
||||
self.testInput0,
|
||||
self.testInput1,
|
||||
]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertFalse(parsed.utest)
|
||||
self.assertEqual(parsed.utest_alpha, 0.314)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_benchmarks_with_remainder(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["benchmarks", self.testInput0, self.testInput1, "d"]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertEqual(parsed.benchmark_options, ["d"])
|
||||
|
||||
def test_benchmarks_with_remainder_after_doubleminus(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["benchmarks", self.testInput0, self.testInput1, "--", "e"]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarks")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertEqual(parsed.benchmark_options, ["e"])
|
||||
|
||||
def test_filters_basic(self):
|
||||
parsed = self.parser.parse_args(["filters", self.testInput0, "c", "d"])
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "filters")
|
||||
self.assertEqual(parsed.test[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.filter_baseline[0], "c")
|
||||
self.assertEqual(parsed.filter_contender[0], "d")
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_filters_with_remainder(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["filters", self.testInput0, "c", "d", "e"]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "filters")
|
||||
self.assertEqual(parsed.test[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.filter_baseline[0], "c")
|
||||
self.assertEqual(parsed.filter_contender[0], "d")
|
||||
self.assertEqual(parsed.benchmark_options, ["e"])
|
||||
|
||||
def test_filters_with_remainder_after_doubleminus(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["filters", self.testInput0, "c", "d", "--", "f"]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "filters")
|
||||
self.assertEqual(parsed.test[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.filter_baseline[0], "c")
|
||||
self.assertEqual(parsed.filter_contender[0], "d")
|
||||
self.assertEqual(parsed.benchmark_options, ["f"])
|
||||
|
||||
def test_benchmarksfiltered_basic(self):
|
||||
parsed = self.parser.parse_args(
|
||||
["benchmarksfiltered", self.testInput0, "c", self.testInput1, "e"]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarksfiltered")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.filter_baseline[0], "c")
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertEqual(parsed.filter_contender[0], "e")
|
||||
self.assertFalse(parsed.benchmark_options)
|
||||
|
||||
def test_benchmarksfiltered_with_remainder(self):
|
||||
parsed = self.parser.parse_args(
|
||||
[
|
||||
"benchmarksfiltered",
|
||||
self.testInput0,
|
||||
"c",
|
||||
self.testInput1,
|
||||
"e",
|
||||
"f",
|
||||
]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarksfiltered")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.filter_baseline[0], "c")
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertEqual(parsed.filter_contender[0], "e")
|
||||
self.assertEqual(parsed.benchmark_options[0], "f")
|
||||
|
||||
def test_benchmarksfiltered_with_remainder_after_doubleminus(self):
|
||||
parsed = self.parser.parse_args(
|
||||
[
|
||||
"benchmarksfiltered",
|
||||
self.testInput0,
|
||||
"c",
|
||||
self.testInput1,
|
||||
"e",
|
||||
"--",
|
||||
"g",
|
||||
]
|
||||
)
|
||||
self.assertFalse(parsed.display_aggregates_only)
|
||||
self.assertTrue(parsed.utest)
|
||||
self.assertEqual(parsed.mode, "benchmarksfiltered")
|
||||
self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
|
||||
self.assertEqual(parsed.filter_baseline[0], "c")
|
||||
self.assertEqual(parsed.test_contender[0].name, self.testInput1)
|
||||
self.assertEqual(parsed.filter_contender[0], "e")
|
||||
self.assertEqual(parsed.benchmark_options[0], "g")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# unittest.main()
|
||||
main()
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
|
||||
# kate: indent-mode python; remove-trailing-spaces modified;
|
||||
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_SameTimes",
|
||||
"iterations": 1000,
|
||||
"real_time": 10,
|
||||
"cpu_time": 10,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_2xFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 50,
|
||||
"cpu_time": 50,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_2xSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 50,
|
||||
"cpu_time": 50,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_1PercentFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_1PercentSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_10PercentFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_10PercentSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_100xSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_100xFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 10000,
|
||||
"cpu_time": 10000,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_10PercentCPUToTime",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_ThirdFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "MyComplexityTest_BigO",
|
||||
"run_name": "MyComplexityTest",
|
||||
"run_type": "aggregate",
|
||||
"aggregate_name": "BigO",
|
||||
"cpu_coefficient": 4.2749856294592886e+00,
|
||||
"real_coefficient": 6.4789275289789780e+00,
|
||||
"big_o": "N",
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "MyComplexityTest_RMS",
|
||||
"run_name": "MyComplexityTest",
|
||||
"run_type": "aggregate",
|
||||
"aggregate_name": "RMS",
|
||||
"rms": 4.5097802512472874e-03
|
||||
},
|
||||
{
|
||||
"name": "BM_NotBadTimeUnit",
|
||||
"iterations": 1000,
|
||||
"real_time": 0.4,
|
||||
"cpu_time": 0.5,
|
||||
"time_unit": "s"
|
||||
},
|
||||
{
|
||||
"name": "BM_DifferentTimeUnit",
|
||||
"iterations": 1,
|
||||
"real_time": 1,
|
||||
"cpu_time": 1,
|
||||
"time_unit": "s"
|
||||
},
|
||||
{
|
||||
"name": "BM_hasLabel",
|
||||
"label": "a label",
|
||||
"iterations": 1,
|
||||
"real_time": 1,
|
||||
"cpu_time": 1,
|
||||
"time_unit": "s"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_SameTimes",
|
||||
"iterations": 1000,
|
||||
"real_time": 10,
|
||||
"cpu_time": 10,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_2xFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 25,
|
||||
"cpu_time": 25,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_2xSlower",
|
||||
"iterations": 20833333,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_1PercentFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 98.9999999,
|
||||
"cpu_time": 98.9999999,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_1PercentSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 100.9999999,
|
||||
"cpu_time": 100.9999999,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_10PercentFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 90,
|
||||
"cpu_time": 90,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_10PercentSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 110,
|
||||
"cpu_time": 110,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_100xSlower",
|
||||
"iterations": 1000,
|
||||
"real_time": 1.0000e+04,
|
||||
"cpu_time": 1.0000e+04,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_100xFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 100,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_10PercentCPUToTime",
|
||||
"iterations": 1000,
|
||||
"real_time": 110,
|
||||
"cpu_time": 90,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_ThirdFaster",
|
||||
"iterations": 1000,
|
||||
"real_time": 66.665,
|
||||
"cpu_time": 66.664,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "MyComplexityTest_BigO",
|
||||
"run_name": "MyComplexityTest",
|
||||
"run_type": "aggregate",
|
||||
"aggregate_name": "BigO",
|
||||
"cpu_coefficient": 5.6215779594361486e+00,
|
||||
"real_coefficient": 5.6288314793554610e+00,
|
||||
"big_o": "N",
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "MyComplexityTest_RMS",
|
||||
"run_name": "MyComplexityTest",
|
||||
"run_type": "aggregate",
|
||||
"aggregate_name": "RMS",
|
||||
"rms": 3.3128901852342174e-03
|
||||
},
|
||||
{
|
||||
"name": "BM_NotBadTimeUnit",
|
||||
"iterations": 1000,
|
||||
"real_time": 0.04,
|
||||
"cpu_time": 0.6,
|
||||
"time_unit": "s"
|
||||
},
|
||||
{
|
||||
"name": "BM_DifferentTimeUnit",
|
||||
"iterations": 1,
|
||||
"real_time": 1,
|
||||
"cpu_time": 1,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_hasLabel",
|
||||
"label": "a label",
|
||||
"iterations": 1,
|
||||
"real_time": 1,
|
||||
"cpu_time": 1,
|
||||
"time_unit": "s"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_Hi",
|
||||
"iterations": 1234,
|
||||
"real_time": 42,
|
||||
"cpu_time": 24,
|
||||
"time_unit": "ms"
|
||||
},
|
||||
{
|
||||
"name": "BM_Zero",
|
||||
"iterations": 1000,
|
||||
"real_time": 10,
|
||||
"cpu_time": 10,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_Zero/4",
|
||||
"iterations": 4000,
|
||||
"real_time": 40,
|
||||
"cpu_time": 40,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "Prefix/BM_Zero",
|
||||
"iterations": 2000,
|
||||
"real_time": 20,
|
||||
"cpu_time": 20,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "Prefix/BM_Zero/3",
|
||||
"iterations": 3000,
|
||||
"real_time": 30,
|
||||
"cpu_time": 30,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_One",
|
||||
"iterations": 5000,
|
||||
"real_time": 5,
|
||||
"cpu_time": 5,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_One/4",
|
||||
"iterations": 2000,
|
||||
"real_time": 20,
|
||||
"cpu_time": 20,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "Prefix/BM_One",
|
||||
"iterations": 1000,
|
||||
"real_time": 10,
|
||||
"cpu_time": 10,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "Prefix/BM_One/3",
|
||||
"iterations": 1500,
|
||||
"real_time": 15,
|
||||
"cpu_time": 15,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_Bye",
|
||||
"iterations": 5321,
|
||||
"real_time": 11,
|
||||
"cpu_time": 63,
|
||||
"time_unit": "ns"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_One",
|
||||
"run_type": "aggregate",
|
||||
"iterations": 1000,
|
||||
"real_time": 10,
|
||||
"cpu_time": 100,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_Two",
|
||||
"iterations": 1000,
|
||||
"real_time": 9,
|
||||
"cpu_time": 90,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_Two",
|
||||
"iterations": 1000,
|
||||
"real_time": 8,
|
||||
"cpu_time": 86,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "short",
|
||||
"run_type": "aggregate",
|
||||
"iterations": 1000,
|
||||
"real_time": 8,
|
||||
"cpu_time": 80,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "short",
|
||||
"run_type": "aggregate",
|
||||
"iterations": 1000,
|
||||
"real_time": 8,
|
||||
"cpu_time": 77,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "medium",
|
||||
"run_type": "iteration",
|
||||
"iterations": 1000,
|
||||
"real_time": 8,
|
||||
"cpu_time": 80,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "medium",
|
||||
"run_type": "iteration",
|
||||
"iterations": 1000,
|
||||
"real_time": 9,
|
||||
"cpu_time": 82,
|
||||
"time_unit": "ns"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_One",
|
||||
"iterations": 1000,
|
||||
"real_time": 9,
|
||||
"cpu_time": 110,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_Two",
|
||||
"run_type": "aggregate",
|
||||
"iterations": 1000,
|
||||
"real_time": 10,
|
||||
"cpu_time": 89,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "BM_Two",
|
||||
"iterations": 1000,
|
||||
"real_time": 7,
|
||||
"cpu_time": 72,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "short",
|
||||
"run_type": "aggregate",
|
||||
"iterations": 1000,
|
||||
"real_time": 7,
|
||||
"cpu_time": 75,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "short",
|
||||
"run_type": "aggregate",
|
||||
"iterations": 762,
|
||||
"real_time": 4.54,
|
||||
"cpu_time": 66.6,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "short",
|
||||
"run_type": "iteration",
|
||||
"iterations": 1000,
|
||||
"real_time": 800,
|
||||
"cpu_time": 1,
|
||||
"time_unit": "ns"
|
||||
},
|
||||
{
|
||||
"name": "medium",
|
||||
"run_type": "iteration",
|
||||
"iterations": 1200,
|
||||
"real_time": 5,
|
||||
"cpu_time": 53,
|
||||
"time_unit": "ns"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "99 family 0 instance 0 repetition 0",
|
||||
"run_type": "iteration",
|
||||
"family_index": 0,
|
||||
"per_family_instance_index": 0,
|
||||
"repetition_index": 0
|
||||
},
|
||||
{
|
||||
"name": "98 family 0 instance 0 repetition 1",
|
||||
"run_type": "iteration",
|
||||
"family_index": 0,
|
||||
"per_family_instance_index": 0,
|
||||
"repetition_index": 1
|
||||
},
|
||||
{
|
||||
"name": "97 family 0 instance 0 aggregate",
|
||||
"run_type": "aggregate",
|
||||
"family_index": 0,
|
||||
"per_family_instance_index": 0,
|
||||
"aggregate_name": "9 aggregate"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "96 family 0 instance 1 repetition 0",
|
||||
"run_type": "iteration",
|
||||
"family_index": 0,
|
||||
"per_family_instance_index": 1,
|
||||
"repetition_index": 0
|
||||
},
|
||||
{
|
||||
"name": "95 family 0 instance 1 repetition 1",
|
||||
"run_type": "iteration",
|
||||
"family_index": 0,
|
||||
"per_family_instance_index": 1,
|
||||
"repetition_index": 1
|
||||
},
|
||||
{
|
||||
"name": "94 family 0 instance 1 aggregate",
|
||||
"run_type": "aggregate",
|
||||
"family_index": 0,
|
||||
"per_family_instance_index": 1,
|
||||
"aggregate_name": "9 aggregate"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"name": "93 family 1 instance 0 repetition 0",
|
||||
"run_type": "iteration",
|
||||
"family_index": 1,
|
||||
"per_family_instance_index": 0,
|
||||
"repetition_index": 0
|
||||
},
|
||||
{
|
||||
"name": "92 family 1 instance 0 repetition 1",
|
||||
"run_type": "iteration",
|
||||
"family_index": 1,
|
||||
"per_family_instance_index": 0,
|
||||
"repetition_index": 1
|
||||
},
|
||||
{
|
||||
"name": "91 family 1 instance 0 aggregate",
|
||||
"run_type": "aggregate",
|
||||
"family_index": 1,
|
||||
"per_family_instance_index": 0,
|
||||
"aggregate_name": "9 aggregate"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "90 family 1 instance 1 repetition 0",
|
||||
"run_type": "iteration",
|
||||
"family_index": 1,
|
||||
"per_family_instance_index": 1,
|
||||
"repetition_index": 0
|
||||
},
|
||||
{
|
||||
"name": "89 family 1 instance 1 repetition 1",
|
||||
"run_type": "iteration",
|
||||
"family_index": 1,
|
||||
"per_family_instance_index": 1,
|
||||
"repetition_index": 1
|
||||
},
|
||||
{
|
||||
"name": "88 family 1 instance 1 aggregate",
|
||||
"run_type": "aggregate",
|
||||
"family_index": 1,
|
||||
"per_family_instance_index": 1,
|
||||
"aggregate_name": "9 aggregate"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "whocares",
|
||||
"run_type": "aggregate",
|
||||
"aggregate_name": "zz",
|
||||
"aggregate_unit": "percentage",
|
||||
"iterations": 1000,
|
||||
"real_time": 0.01,
|
||||
"cpu_time": 0.10,
|
||||
"time_unit": "ns"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "whocares",
|
||||
"run_type": "aggregate",
|
||||
"aggregate_name": "zz",
|
||||
"aggregate_unit": "percentage",
|
||||
"iterations": 1000,
|
||||
"real_time": 0.005,
|
||||
"cpu_time": 0.15,
|
||||
"time_unit": "ns"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_ManyRepetitions",
|
||||
"iterations": 1000,
|
||||
"real_time": 1,
|
||||
"cpu_time": 1000,
|
||||
"time_unit": "s"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
"library_build_type": "release"
|
||||
},
|
||||
"benchmarks": [
|
||||
{
|
||||
"name": "BM_ManyRepetitions",
|
||||
"iterations": 1000,
|
||||
"real_time": 1000,
|
||||
"cpu_time": 1,
|
||||
"time_unit": "s"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Google Benchmark tooling"""
|
||||
|
||||
__author__ = "Eric Fiselier"
|
||||
__email__ = "eric@efcs.ca"
|
||||
__versioninfo__ = (0, 5, 0)
|
||||
__version__ = ".".join(str(v) for v in __versioninfo__) + "dev"
|
||||
|
||||
__all__ = [] # type: ignore
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,229 @@
|
||||
"""util.py - General utilities for running, loading, and processing
|
||||
benchmarks
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# Input file type enumeration
|
||||
IT_Invalid = 0
|
||||
IT_JSON = 1
|
||||
IT_Executable = 2
|
||||
|
||||
_num_magic_bytes = 2 if sys.platform.startswith("win") else 4
|
||||
|
||||
|
||||
def is_executable_file(filename):
|
||||
"""
|
||||
Return 'True' if 'filename' names a valid file which is likely
|
||||
an executable. A file is considered an executable if it starts with the
|
||||
magic bytes for a EXE, Mach O, or ELF file.
|
||||
"""
|
||||
if not os.path.isfile(filename):
|
||||
return False
|
||||
with open(filename, mode="rb") as f:
|
||||
magic_bytes = f.read(_num_magic_bytes)
|
||||
if sys.platform == "darwin":
|
||||
return magic_bytes in [
|
||||
b"\xfe\xed\xfa\xce", # MH_MAGIC
|
||||
b"\xce\xfa\xed\xfe", # MH_CIGAM
|
||||
b"\xfe\xed\xfa\xcf", # MH_MAGIC_64
|
||||
b"\xcf\xfa\xed\xfe", # MH_CIGAM_64
|
||||
b"\xca\xfe\xba\xbe", # FAT_MAGIC
|
||||
b"\xbe\xba\xfe\xca", # FAT_CIGAM
|
||||
]
|
||||
elif sys.platform.startswith("win"):
|
||||
return magic_bytes == b"MZ"
|
||||
else:
|
||||
return magic_bytes == b"\x7fELF"
|
||||
|
||||
|
||||
def is_json_file(filename):
|
||||
"""
|
||||
Returns 'True' if 'filename' names a valid JSON output file.
|
||||
'False' otherwise.
|
||||
"""
|
||||
try:
|
||||
with open(filename) as f:
|
||||
json.load(f)
|
||||
return True
|
||||
except BaseException:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def classify_input_file(filename):
|
||||
"""
|
||||
Return a tuple (type, msg) where 'type' specifies the classified type
|
||||
of 'filename'. If 'type' is 'IT_Invalid' then 'msg' is a human readable
|
||||
string representing the error.
|
||||
"""
|
||||
ftype = IT_Invalid
|
||||
err_msg = None
|
||||
if not os.path.exists(filename):
|
||||
err_msg = "'%s' does not exist" % filename
|
||||
elif not os.path.isfile(filename):
|
||||
err_msg = "'%s' does not name a file" % filename
|
||||
elif is_executable_file(filename):
|
||||
ftype = IT_Executable
|
||||
elif is_json_file(filename):
|
||||
ftype = IT_JSON
|
||||
else:
|
||||
err_msg = (
|
||||
"'%s' does not name a valid benchmark executable or JSON file"
|
||||
% filename
|
||||
)
|
||||
return ftype, err_msg
|
||||
|
||||
|
||||
def check_input_file(filename):
|
||||
"""
|
||||
Classify the file named by 'filename' and return the classification.
|
||||
If the file is classified as 'IT_Invalid' print an error message and exit
|
||||
the program.
|
||||
"""
|
||||
ftype, msg = classify_input_file(filename)
|
||||
if ftype == IT_Invalid:
|
||||
print("Invalid input file: %s" % msg)
|
||||
sys.exit(1)
|
||||
return ftype
|
||||
|
||||
|
||||
def find_benchmark_flag(prefix, benchmark_flags):
|
||||
"""
|
||||
Search the specified list of flags for a flag matching `<prefix><arg>` and
|
||||
if it is found return the arg it specifies. If specified more than once the
|
||||
last value is returned. If the flag is not found None is returned.
|
||||
"""
|
||||
assert prefix.startswith("--")
|
||||
assert prefix.endswith("=")
|
||||
result = None
|
||||
for f in benchmark_flags:
|
||||
if f.startswith(prefix):
|
||||
result = f[len(prefix) :]
|
||||
return result
|
||||
|
||||
|
||||
def remove_benchmark_flags(prefix, benchmark_flags):
|
||||
"""
|
||||
Return a new list containing the specified benchmark_flags except those
|
||||
with the specified prefix.
|
||||
"""
|
||||
assert prefix.startswith("--")
|
||||
assert prefix.endswith("=")
|
||||
return [f for f in benchmark_flags if not f.startswith(prefix)]
|
||||
|
||||
|
||||
def load_benchmark_results(fname, benchmark_filter):
|
||||
"""
|
||||
Read benchmark output from a file and return the JSON object.
|
||||
|
||||
Apply benchmark_filter, a regular expression, with nearly the same
|
||||
semantics of the --benchmark_filter argument. May be None.
|
||||
Note: the Python regular expression engine is used instead of the
|
||||
one used by the C++ code, which may produce different results
|
||||
in complex cases.
|
||||
|
||||
REQUIRES: 'fname' names a file containing JSON benchmark output.
|
||||
"""
|
||||
|
||||
def benchmark_wanted(benchmark):
|
||||
if benchmark_filter is None:
|
||||
return True
|
||||
name = benchmark.get("run_name", None) or benchmark["name"]
|
||||
return re.search(benchmark_filter, name) is not None
|
||||
|
||||
with open(fname) as f:
|
||||
results = json.load(f)
|
||||
if "json_schema_version" in results.get("context", {}):
|
||||
json_schema_version = results["context"]["json_schema_version"]
|
||||
if json_schema_version != 1:
|
||||
print(
|
||||
f"In {fname}, got unnsupported JSON schema version:"
|
||||
f" {json_schema_version}, expected 1"
|
||||
)
|
||||
sys.exit(1)
|
||||
if "benchmarks" in results:
|
||||
results["benchmarks"] = list(
|
||||
filter(benchmark_wanted, results["benchmarks"])
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def sort_benchmark_results(result):
|
||||
benchmarks = result["benchmarks"]
|
||||
|
||||
# From inner key to the outer key!
|
||||
benchmarks = sorted(
|
||||
benchmarks,
|
||||
key=lambda benchmark: benchmark.get("repetition_index", -1),
|
||||
)
|
||||
benchmarks = sorted(
|
||||
benchmarks,
|
||||
key=lambda benchmark: 1
|
||||
if "run_type" in benchmark and benchmark["run_type"] == "aggregate"
|
||||
else 0,
|
||||
)
|
||||
benchmarks = sorted(
|
||||
benchmarks,
|
||||
key=lambda benchmark: benchmark.get("per_family_instance_index", -1),
|
||||
)
|
||||
benchmarks = sorted(
|
||||
benchmarks,
|
||||
key=lambda benchmark: benchmark.get("family_index", -1),
|
||||
)
|
||||
|
||||
result["benchmarks"] = benchmarks
|
||||
return result
|
||||
|
||||
|
||||
def run_benchmark(exe_name, benchmark_flags):
|
||||
"""
|
||||
Run a benchmark specified by 'exe_name' with the specified
|
||||
'benchmark_flags'. The benchmark is run directly as a subprocess to preserve
|
||||
real time console output.
|
||||
RETURNS: A JSON object representing the benchmark output
|
||||
"""
|
||||
output_name = find_benchmark_flag("--benchmark_out=", benchmark_flags)
|
||||
is_temp_output = False
|
||||
if output_name is None:
|
||||
is_temp_output = True
|
||||
thandle, output_name = tempfile.mkstemp()
|
||||
os.close(thandle)
|
||||
benchmark_flags = [
|
||||
*list(benchmark_flags),
|
||||
"--benchmark_out=%s" % output_name,
|
||||
]
|
||||
|
||||
cmd = [exe_name, *benchmark_flags]
|
||||
print("RUNNING: %s" % " ".join(cmd))
|
||||
exitCode = subprocess.call(cmd)
|
||||
if exitCode != 0:
|
||||
print("TEST FAILED...")
|
||||
sys.exit(exitCode)
|
||||
json_res = load_benchmark_results(output_name, None)
|
||||
if is_temp_output:
|
||||
os.unlink(output_name)
|
||||
return json_res
|
||||
|
||||
|
||||
def run_or_load_benchmark(filename, benchmark_flags):
|
||||
"""
|
||||
Get the results for a specified benchmark. If 'filename' specifies
|
||||
an executable benchmark then the results are generated by running the
|
||||
benchmark. Otherwise 'filename' must name a valid JSON output file,
|
||||
which is loaded and the result returned.
|
||||
"""
|
||||
ftype = check_input_file(filename)
|
||||
if ftype == IT_JSON:
|
||||
benchmark_filter = find_benchmark_flag(
|
||||
"--benchmark_filter=", benchmark_flags
|
||||
)
|
||||
return load_benchmark_results(filename, benchmark_filter)
|
||||
if ftype == IT_Executable:
|
||||
return run_benchmark(filename, benchmark_flags)
|
||||
raise ValueError("Unknown file type %s" % ftype)
|
||||
@@ -0,0 +1,242 @@
|
||||
"""Build rule for libpfm, which is required to collect performance counters for BENCHMARK_ENABLE_LIBPFM builds."""
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
AARCH32_SRCS_COMMON = [
|
||||
"lib/pfmlib_arm.c",
|
||||
"lib/pfmlib_arm_armv7_pmuv1.c",
|
||||
"lib/pfmlib_arm_armv6.c",
|
||||
"lib/pfmlib_arm_armv8.c",
|
||||
"lib/pfmlib_tx2_unc_perf_event.c",
|
||||
]
|
||||
|
||||
AARCH32_SRCS_LINUX = [
|
||||
"lib/pfmlib_arm_perf_event.c",
|
||||
]
|
||||
|
||||
AARCH64_SRCS_COMMON = [
|
||||
"lib/pfmlib_arm.c",
|
||||
"lib/pfmlib_arm_armv8.c",
|
||||
"lib/pfmlib_tx2_unc_perf_event.c",
|
||||
]
|
||||
|
||||
AARCH64_SRCS_LINUX = [
|
||||
"lib/pfmlib_arm_perf_event.c",
|
||||
]
|
||||
|
||||
MIPS_SRCS_COMMON = [
|
||||
"lib/pfmlib_mips.c",
|
||||
"lib/pfmlib_mips_74k.c",
|
||||
]
|
||||
|
||||
MIPS_SRCS_LINUX = [
|
||||
"lib/pfmlib_mips_perf_event.c",
|
||||
]
|
||||
|
||||
POWERPC_SRCS_COMMON = [
|
||||
"lib/pfmlib_powerpc.c",
|
||||
"lib/pfmlib_power4.c",
|
||||
"lib/pfmlib_ppc970.c",
|
||||
"lib/pfmlib_power5.c",
|
||||
"lib/pfmlib_power6.c",
|
||||
"lib/pfmlib_power7.c",
|
||||
"lib/pfmlib_torrent.c",
|
||||
"lib/pfmlib_power8.c",
|
||||
"lib/pfmlib_power9.c",
|
||||
"lib/pfmlib_powerpc_nest.c",
|
||||
]
|
||||
|
||||
POWERPC_SRCS_LINUX = [
|
||||
"lib/pfmlib_powerpc_perf_event.c",
|
||||
]
|
||||
|
||||
S390X_SRCS_COMMON = [
|
||||
"lib/pfmlib_s390x_cpumf.c",
|
||||
]
|
||||
|
||||
S390X_SRCS_LINUX = [
|
||||
"lib/pfmlib_s390x_perf_event.c",
|
||||
]
|
||||
|
||||
X86_64_SRCS_COMMON = [
|
||||
"lib/pfmlib_amd64.c",
|
||||
"lib/pfmlib_intel_core.c",
|
||||
"lib/pfmlib_intel_x86.c",
|
||||
"lib/pfmlib_intel_x86_arch.c",
|
||||
"lib/pfmlib_intel_atom.c",
|
||||
"lib/pfmlib_intel_nhm_unc.c",
|
||||
"lib/pfmlib_intel_nhm.c",
|
||||
"lib/pfmlib_intel_wsm.c",
|
||||
"lib/pfmlib_intel_snb.c",
|
||||
"lib/pfmlib_intel_snb_unc.c",
|
||||
"lib/pfmlib_intel_ivb.c",
|
||||
"lib/pfmlib_intel_ivb_unc.c",
|
||||
"lib/pfmlib_intel_hsw.c",
|
||||
"lib/pfmlib_intel_bdw.c",
|
||||
"lib/pfmlib_intel_skl.c",
|
||||
"lib/pfmlib_intel_icl.c",
|
||||
"lib/pfmlib_intel_rapl.c",
|
||||
"lib/pfmlib_intel_snbep_unc.c",
|
||||
"lib/pfmlib_intel_snbep_unc_cbo.c",
|
||||
"lib/pfmlib_intel_snbep_unc_ha.c",
|
||||
"lib/pfmlib_intel_snbep_unc_imc.c",
|
||||
"lib/pfmlib_intel_snbep_unc_pcu.c",
|
||||
"lib/pfmlib_intel_snbep_unc_qpi.c",
|
||||
"lib/pfmlib_intel_snbep_unc_ubo.c",
|
||||
"lib/pfmlib_intel_snbep_unc_r2pcie.c",
|
||||
"lib/pfmlib_intel_snbep_unc_r3qpi.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_cbo.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_ha.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_imc.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_pcu.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_qpi.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_ubo.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_r2pcie.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_r3qpi.c",
|
||||
"lib/pfmlib_intel_ivbep_unc_irp.c",
|
||||
"lib/pfmlib_intel_hswep_unc_cbo.c",
|
||||
"lib/pfmlib_intel_hswep_unc_ha.c",
|
||||
"lib/pfmlib_intel_hswep_unc_imc.c",
|
||||
"lib/pfmlib_intel_hswep_unc_pcu.c",
|
||||
"lib/pfmlib_intel_hswep_unc_qpi.c",
|
||||
"lib/pfmlib_intel_hswep_unc_ubo.c",
|
||||
"lib/pfmlib_intel_hswep_unc_r2pcie.c",
|
||||
"lib/pfmlib_intel_hswep_unc_r3qpi.c",
|
||||
"lib/pfmlib_intel_hswep_unc_irp.c",
|
||||
"lib/pfmlib_intel_hswep_unc_sbo.c",
|
||||
"lib/pfmlib_intel_bdx_unc_cbo.c",
|
||||
"lib/pfmlib_intel_bdx_unc_ubo.c",
|
||||
"lib/pfmlib_intel_bdx_unc_sbo.c",
|
||||
"lib/pfmlib_intel_bdx_unc_ha.c",
|
||||
"lib/pfmlib_intel_bdx_unc_imc.c",
|
||||
"lib/pfmlib_intel_bdx_unc_irp.c",
|
||||
"lib/pfmlib_intel_bdx_unc_pcu.c",
|
||||
"lib/pfmlib_intel_bdx_unc_qpi.c",
|
||||
"lib/pfmlib_intel_bdx_unc_r2pcie.c",
|
||||
"lib/pfmlib_intel_bdx_unc_r3qpi.c",
|
||||
"lib/pfmlib_intel_skx_unc_cha.c",
|
||||
"lib/pfmlib_intel_skx_unc_iio.c",
|
||||
"lib/pfmlib_intel_skx_unc_imc.c",
|
||||
"lib/pfmlib_intel_skx_unc_irp.c",
|
||||
"lib/pfmlib_intel_skx_unc_m2m.c",
|
||||
"lib/pfmlib_intel_skx_unc_m3upi.c",
|
||||
"lib/pfmlib_intel_skx_unc_pcu.c",
|
||||
"lib/pfmlib_intel_skx_unc_ubo.c",
|
||||
"lib/pfmlib_intel_skx_unc_upi.c",
|
||||
"lib/pfmlib_intel_knc.c",
|
||||
"lib/pfmlib_intel_slm.c",
|
||||
"lib/pfmlib_intel_tmt.c",
|
||||
"lib/pfmlib_intel_knl.c",
|
||||
"lib/pfmlib_intel_knl_unc_imc.c",
|
||||
"lib/pfmlib_intel_knl_unc_edc.c",
|
||||
"lib/pfmlib_intel_knl_unc_cha.c",
|
||||
"lib/pfmlib_intel_knl_unc_m2pcie.c",
|
||||
"lib/pfmlib_intel_glm.c",
|
||||
"lib/pfmlib_intel_netburst.c",
|
||||
"lib/pfmlib_amd64_k7.c",
|
||||
"lib/pfmlib_amd64_k8.c",
|
||||
"lib/pfmlib_amd64_fam10h.c",
|
||||
"lib/pfmlib_amd64_fam11h.c",
|
||||
"lib/pfmlib_amd64_fam12h.c",
|
||||
"lib/pfmlib_amd64_fam14h.c",
|
||||
"lib/pfmlib_amd64_fam15h.c",
|
||||
"lib/pfmlib_amd64_fam17h.c",
|
||||
"lib/pfmlib_amd64_fam16h.c",
|
||||
]
|
||||
|
||||
X86_SRCS_COMMON = X86_64_SRCS_COMMON + [
|
||||
"lib/pfmlib_intel_coreduo.c",
|
||||
"lib/pfmlib_intel_p6.c",
|
||||
]
|
||||
|
||||
filegroup(
|
||||
name = "cpu_srcs",
|
||||
srcs = select({
|
||||
"@platforms//cpu:x86_32": X86_SRCS_COMMON,
|
||||
"@platforms//cpu:x86_64": X86_64_SRCS_COMMON,
|
||||
"@platforms//cpu:aarch32": AARCH32_SRCS_COMMON,
|
||||
"@platforms//cpu:aarch64": AARCH64_SRCS_COMMON,
|
||||
"@platforms//cpu:mips64": MIPS_SRCS_COMMON,
|
||||
"@platforms//cpu:ppc32": POWERPC_SRCS_COMMON,
|
||||
"@platforms//cpu:ppc64le": POWERPC_SRCS_COMMON,
|
||||
"@platforms//cpu:ppc": POWERPC_SRCS_COMMON,
|
||||
"@platforms//cpu:s390x": S390X_SRCS_COMMON,
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "linux_srcs",
|
||||
srcs = select({
|
||||
"@platforms//cpu:aarch32": AARCH32_SRCS_LINUX,
|
||||
"@platforms//cpu:aarch64": AARCH64_SRCS_LINUX,
|
||||
"@platforms//cpu:mips64": MIPS_SRCS_LINUX,
|
||||
"@platforms//cpu:ppc32": POWERPC_SRCS_LINUX,
|
||||
"@platforms//cpu:ppc64le": POWERPC_SRCS_LINUX,
|
||||
"@platforms//cpu:ppc": POWERPC_SRCS_LINUX,
|
||||
"@platforms//cpu:s390x": S390X_SRCS_LINUX,
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "srcs",
|
||||
srcs = [
|
||||
"lib/pfmlib_common.c",
|
||||
"lib/pfmlib_perf_event.c",
|
||||
"lib/pfmlib_perf_event_pmu.c",
|
||||
"lib/pfmlib_perf_event_priv.h",
|
||||
"lib/pfmlib_perf_event_raw.c",
|
||||
"lib/pfmlib_torrent.c",
|
||||
"lib/pfmlib_tx2_unc_perf_event.c",
|
||||
":cpu_srcs",
|
||||
] + select({
|
||||
"@platforms//os:linux": [":linux_srcs"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "pfm",
|
||||
srcs = [
|
||||
":srcs",
|
||||
],
|
||||
hdrs = glob([
|
||||
"include/perfmon/*.h",
|
||||
]),
|
||||
copts = [
|
||||
"-Wno-format-truncation",
|
||||
"-Wno-use-after-free",
|
||||
"-fPIC",
|
||||
"-D_REENTRANT",
|
||||
"-fvisibility=hidden",
|
||||
] + select({
|
||||
"@platforms//cpu:aarch32": ["-DCONFIG_PFMLIB_ARCH_ARM"],
|
||||
"@platforms//cpu:aarch64": ["-DCONFIG_PFMLIB_ARCH_ARM64"],
|
||||
"@platforms//cpu:mips64": ["-DCONFIG_PFMLIB_ARCH_MIPS"],
|
||||
"@platforms//cpu:ppc32": ["-DCONFIG_PFMLIB_ARCH_POWERPC"],
|
||||
"@platforms//cpu:ppc64le": ["-DCONFIG_PFMLIB_ARCH_POWERPC"],
|
||||
"@platforms//cpu:ppc": ["-DCONFIG_PFMLIB_ARCH_POWERPC"],
|
||||
"@platforms//cpu:s390x": ["-DCONFIG_PFMLIB_ARCH_S390X"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
includes = [
|
||||
"include",
|
||||
"lib",
|
||||
],
|
||||
strip_include_prefix = "include",
|
||||
textual_hdrs = glob([
|
||||
"lib/**/*.h",
|
||||
]),
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "libpfm",
|
||||
actual = ":pfm",
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
numpy == 2.5.1
|
||||
scipy == 1.18.0
|
||||
Executable
+163
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
strip_asm.py - Cleanup ASM output for the specified file
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
||||
def find_used_labels(asm):
|
||||
found = set()
|
||||
label_re = re.compile(r"\s*j[a-z]+\s+\.L([a-zA-Z0-9][a-zA-Z0-9_]*)")
|
||||
for line in asm.splitlines():
|
||||
m = label_re.match(line)
|
||||
if m:
|
||||
found.add(".L%s" % m.group(1))
|
||||
return found
|
||||
|
||||
|
||||
def normalize_labels(asm):
|
||||
decls = set()
|
||||
label_decl = re.compile("^[.]{0,1}L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)")
|
||||
for line in asm.splitlines():
|
||||
m = label_decl.match(line)
|
||||
if m:
|
||||
decls.add(m.group(0))
|
||||
if len(decls) == 0:
|
||||
return asm
|
||||
needs_dot = next(iter(decls))[0] != "."
|
||||
if not needs_dot:
|
||||
return asm
|
||||
for ld in decls:
|
||||
asm = re.sub(r"(^|\s+)" + ld + r"(?=:|\s)", "\\1." + ld, asm)
|
||||
return asm
|
||||
|
||||
|
||||
def transform_labels(asm):
|
||||
asm = normalize_labels(asm)
|
||||
used_decls = find_used_labels(asm)
|
||||
new_asm = ""
|
||||
label_decl = re.compile(r"^\.L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)")
|
||||
for line in asm.splitlines():
|
||||
m = label_decl.match(line)
|
||||
if not m or m.group(0) in used_decls:
|
||||
new_asm += line
|
||||
new_asm += "\n"
|
||||
return new_asm
|
||||
|
||||
|
||||
def is_identifier(tk):
|
||||
if len(tk) == 0:
|
||||
return False
|
||||
first = tk[0]
|
||||
if not first.isalpha() and first != "_":
|
||||
return False
|
||||
for i in range(1, len(tk)):
|
||||
c = tk[i]
|
||||
if not c.isalnum() and c != "_":
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def process_identifiers(line):
|
||||
"""
|
||||
process_identifiers - process all identifiers and modify them to have
|
||||
consistent names across all platforms; specifically across ELF and MachO.
|
||||
For example, MachO inserts an additional understore at the beginning of
|
||||
names. This function removes that.
|
||||
"""
|
||||
parts = re.split(r"([a-zA-Z0-9_]+)", line)
|
||||
new_line = ""
|
||||
for tk in parts:
|
||||
if is_identifier(tk) and (
|
||||
tk.startswith("__Z")
|
||||
or (
|
||||
tk.startswith("_")
|
||||
and len(tk) > 1
|
||||
and tk[1].isalpha()
|
||||
and tk[1] != "Z"
|
||||
)
|
||||
):
|
||||
tk = tk[1:]
|
||||
new_line += tk
|
||||
return new_line
|
||||
|
||||
|
||||
def process_asm(asm):
|
||||
"""
|
||||
Strip the ASM of unwanted directives and lines
|
||||
"""
|
||||
new_contents = ""
|
||||
asm = transform_labels(asm)
|
||||
|
||||
# TODO: Add more things we want to remove
|
||||
discard_regexes = [
|
||||
re.compile(r"\s+\..*$"), # directive
|
||||
re.compile(r"\s*#(NO_APP|APP)$"), # inline ASM
|
||||
re.compile(r"\s*#.*$"), # comment line
|
||||
re.compile(
|
||||
r"\s*\.globa?l\s*([.a-zA-Z_][a-zA-Z0-9$_.]*)"
|
||||
), # global directive
|
||||
re.compile(
|
||||
r"\s*\.(string|asciz|ascii|[1248]?byte|short|word|long|quad|value|zero)"
|
||||
),
|
||||
]
|
||||
keep_regexes: list[re.Pattern] = []
|
||||
fn_label_def = re.compile("^[a-zA-Z_][a-zA-Z0-9_.]*:")
|
||||
for line in asm.splitlines():
|
||||
# Remove Mach-O attribute
|
||||
line = line.replace("@GOTPCREL", "")
|
||||
add_line = True
|
||||
for reg in discard_regexes:
|
||||
if reg.match(line) is not None:
|
||||
add_line = False
|
||||
break
|
||||
for reg in keep_regexes:
|
||||
if reg.match(line) is not None:
|
||||
add_line = True
|
||||
break
|
||||
if add_line:
|
||||
if fn_label_def.match(line) and len(new_contents) != 0:
|
||||
new_contents += "\n"
|
||||
line = process_identifiers(line)
|
||||
new_contents += line
|
||||
new_contents += "\n"
|
||||
return new_contents
|
||||
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(description="generate a stripped assembly file")
|
||||
parser.add_argument(
|
||||
"input",
|
||||
metavar="input",
|
||||
type=str,
|
||||
nargs=1,
|
||||
help="An input assembly file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"out", metavar="output", type=str, nargs=1, help="The output file"
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
input = args.input[0]
|
||||
output = args.out[0]
|
||||
if not os.path.isfile(input):
|
||||
print("ERROR: input file '%s' does not exist" % input)
|
||||
sys.exit(1)
|
||||
|
||||
with open(input) as f:
|
||||
contents = f.read()
|
||||
new_contents = process_asm(contents)
|
||||
with open(output, "w") as f:
|
||||
f.write(new_contents)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
|
||||
# kate: indent-mode python; remove-trailing-spaces modified;
|
||||
Reference in New Issue
Block a user