| 46 | |
| 47 | |
| 48 | class Report: |
| 49 | def __init__(self, cycle_number: int) -> None: |
| 50 | self.cycle_number = cycle_number |
| 51 | """ 1-based cycle number. """ |
| 52 | self._result_by_scenario_name: dict[str, BenchmarkScenarioResult] = dict() |
| 53 | |
| 54 | def add_scenario_result(self, result: BenchmarkScenarioResult) -> None: |
| 55 | assert ( |
| 56 | result.scenario_name not in self._result_by_scenario_name.keys() |
| 57 | ), f"Result of scenario {result.scenario_name} already present" |
| 58 | self._result_by_scenario_name[result.scenario_name] = result |
| 59 | |
| 60 | def get_scenario_names(self) -> list[str]: |
| 61 | return list(self._result_by_scenario_name.keys()) |
| 62 | |
| 63 | def as_string(self, use_colors: bool, limit_to_scenario: str | None = None) -> str: |
| 64 | output_lines = [] |
| 65 | |
| 66 | output_lines.append( |
| 67 | f"{'NAME':<35} | {'TYPE':<15} | {'THIS':^15} | {'OTHER':^15} | {'UNIT':^6} | {'THRESHOLD':^10} | {'Regression?':^13} | 'THIS' is" |
| 68 | ) |
| 69 | output_lines.append("-" * 152) |
| 70 | |
| 71 | for scenario_result in self._result_by_scenario_name.values(): |
| 72 | evaluator = RelativeThresholdEvaluator(scenario_result.scenario_class) |
| 73 | for metric in scenario_result.metrics: |
| 74 | if not metric.has_values(): |
| 75 | continue |
| 76 | |
| 77 | if ( |
| 78 | limit_to_scenario is not None |
| 79 | and scenario_result.scenario_name != limit_to_scenario |
| 80 | ): |
| 81 | continue |
| 82 | |
| 83 | regression = "!!YES!!" if evaluator.is_regression(metric) else "no" |
| 84 | threshold = f"{(evaluator.get_threshold(metric) * 100):.0f}%" |
| 85 | output_lines.append( |
| 86 | f"{scenario_result.scenario_name:<35} | {metric.measurement_type:<15} | {metric.this_as_str():>15} | {metric.other_as_str():>15} | {metric.unit():^6} | {threshold:^10} | {regression:^13} | {evaluator.human_readable(metric, use_colors)}" |
| 87 | ) |
| 88 | |
| 89 | return "\n".join(output_lines) |
| 90 | |
| 91 | def __str__(self) -> str: |
| 92 | return self.as_string(use_colors=False) |
| 93 | |
| 94 | def measurements_of_this( |
| 95 | self, scenario_name: str |
| 96 | ) -> dict[MeasurementType, ReportMeasurement]: |
| 97 | scenario_result = self.get_scenario_result_by_name(scenario_name) |
| 98 | |
| 99 | this_results = dict() |
| 100 | for metric in scenario_result.metrics: |
| 101 | this_results[metric.measurement_type] = ReportMeasurement( |
| 102 | metric.points_this() |
| 103 | ) |
| 104 | |
| 105 | return this_results |