CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
141 lines
5.1 KiB
Python
141 lines
5.1 KiB
Python
# DExTer : Debugging Experience Tester
|
|
# ~~~~~~ ~ ~~ ~ ~~
|
|
#
|
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# See https://llvm.org/LICENSE.txt for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
"""Produce metric results from the results of a comparison of a DexterScript and debugger output.
|
|
"""
|
|
|
|
from typing import Any, Dict, List, Union
|
|
|
|
from dex.evaluation.ExpectMatch import DebuggerExpectMatch
|
|
from dex.test_script.Nodes import Expect, Value
|
|
|
|
|
|
class Metric:
|
|
def __init__(self, improves_asc=True):
|
|
self.improves_asc = improves_asc
|
|
|
|
def as_scalar(self) -> float:
|
|
raise NotImplementedError()
|
|
|
|
def aggregate(self, other):
|
|
raise NotImplementedError()
|
|
|
|
# Returns 1 if this metric is better than "other", -1 if it worse, and 0 if it is the same.
|
|
def compare(self, other):
|
|
a = self.as_scalar()
|
|
b = other.as_scalar()
|
|
if not self.improves_asc:
|
|
a, b = b, a
|
|
if a > b:
|
|
return 1
|
|
elif a < b:
|
|
return -1
|
|
else:
|
|
return 0
|
|
|
|
|
|
class ScalarMetric(Metric):
|
|
def __init__(self, value: Union[int, float], improves_asc=True):
|
|
self.value = value
|
|
super().__init__(improves_asc)
|
|
|
|
def as_scalar(self) -> float:
|
|
return float(self.value)
|
|
|
|
def aggregate(self, other):
|
|
assert (
|
|
self.improves_asc == other.improves_asc
|
|
), "Trying to aggregate different metrics?"
|
|
return ScalarMetric(self.value + other.value, self.improves_asc)
|
|
|
|
def __repr__(self):
|
|
return f"{self.value}"
|
|
|
|
|
|
class FractionMetric(Metric):
|
|
def __init__(self, numerator: int, denominator: int, improves_asc=True):
|
|
self.num = numerator
|
|
self.dom = denominator
|
|
super().__init__(improves_asc)
|
|
|
|
def as_scalar(self) -> float:
|
|
if self.dom == 0:
|
|
return float("nan")
|
|
return float(self.num) / float(self.dom)
|
|
|
|
def as_pct(self) -> float:
|
|
return self.as_scalar() * 100
|
|
|
|
def aggregate(self, other):
|
|
assert (
|
|
self.improves_asc == other.improves_asc
|
|
), "Trying to aggregate different metrics?"
|
|
return FractionMetric(
|
|
self.num + other.num, self.dom + other.dom, self.improves_asc
|
|
)
|
|
|
|
def __repr__(self):
|
|
return f"{self.as_pct():.1f}% ({self.num}/{self.dom})"
|
|
|
|
|
|
def serialize_metric_to_json(metric):
|
|
if isinstance(metric, ScalarMetric):
|
|
return metric.value
|
|
elif isinstance(metric, FractionMetric):
|
|
return metric.as_pct()
|
|
raise Exception("Invalid metric type!")
|
|
|
|
|
|
def get_variable_metrics(
|
|
expect: Expect, expected_values: Any, matches: List[DebuggerExpectMatch]
|
|
) -> Dict[str, Metric]:
|
|
"""Given an Expect node with its expected values and a list of all matches for that Expect in a debugger session,
|
|
returns the computed metrics for that Expect node."""
|
|
assert isinstance(expect, Value), "Non-Value expects currently unsupported"
|
|
if not isinstance(expected_values, list):
|
|
expected_values = [expected_values]
|
|
num_total_steps = len(matches)
|
|
seen_expected_values = set()
|
|
num_correct_steps = 0
|
|
num_missing_var_steps = 0
|
|
num_unexpected_value_steps = 0
|
|
for match in matches:
|
|
if match.match_result:
|
|
seen_expected_values.add(match.expected)
|
|
num_correct_steps += 1
|
|
elif match.actual_result is None:
|
|
num_missing_var_steps += 1
|
|
else:
|
|
num_unexpected_value_steps += 1
|
|
num_seen_values = sum(ev in seen_expected_values for ev in expected_values)
|
|
# And finally produce the metrics map and add the new result to the list.
|
|
metrics = {
|
|
# The number of steps. Though this is not a useful metric in itself, it may be useful to see in tandem with
|
|
# other variables.
|
|
"total_watched_steps": ScalarMetric(num_total_steps),
|
|
# The number of steps where the expected value sequence was observed.
|
|
"correct_steps": ScalarMetric(num_correct_steps),
|
|
# The number of steps which did not match the expected value sequence.
|
|
"incorrect_steps": ScalarMetric(
|
|
num_total_steps - num_correct_steps, improves_asc=False
|
|
),
|
|
# The number of steps where the watched variable/expression was not available in the debugger.
|
|
"missing_var_steps": ScalarMetric(num_missing_var_steps, improves_asc=False),
|
|
# The number of steps where the watched variable/expression had a value not in the set of expected values.
|
|
"unexpected_value_steps": ScalarMetric(
|
|
num_unexpected_value_steps, improves_asc=False
|
|
),
|
|
# The % of steps where the expected value sequence was observed.
|
|
"correct_step_coverage": FractionMetric(num_correct_steps, num_total_steps),
|
|
# The number of expected values that were observed at least once.
|
|
"seen_values": ScalarMetric(num_seen_values),
|
|
# The number of expected values that were not observed.
|
|
"missing_values": ScalarMetric(
|
|
len(expected_values) - num_seen_values, improves_asc=False
|
|
),
|
|
}
|
|
return metrics
|