release generate

This commit is contained in:
2026-01-25 16:01:34 +03:00
parent 46c1ec02fd
commit dfe482c545
15 changed files with 369 additions and 2 deletions
+24 -1
View File
@@ -1,5 +1,6 @@
import re
from datetime import datetime
from importlib.metadata import version
from pathlib import Path
from rich.console import Console
@@ -14,6 +15,7 @@ from .benchmarks.entity import benchmarks as registered_benchmarks
from .services.report_generator import ReportGenerator
from .services.system_info_reader import get_system_info
from .services.diagram_generator import DiagramGenerator
from .services.release_generator import ReleaseGenerator
console = Console()
router = Router(title="Metrics commands:", disable_redirect_stdout=True)
@@ -106,7 +108,28 @@ def run_type_handler(response: Response) -> None:
@router.command(Command("release-generate", description="Generate release report"))
def release_generate_handler(_: Response) -> None:
console.print("[yellow]Release report generation not implemented yet[/yellow]")
lib_version = version("argenta")
console.print(f"[cyan]Generating release report for version:[/cyan] [bold]{lib_version}[/bold]")
console.print("[dim]Running benchmarks (1000 iterations, GC disabled)...[/dim]\n")
type_grouped_benchmarks: list[BenchmarkGroupResult] = registered_benchmarks.run_benchmarks_grouped_by_type(
iterations=1000,
is_gc_disabled=True
)
release_generator = ReleaseGenerator(lib_version)
output_dir = release_generator.generate_release(type_grouped_benchmarks)
console.print(f"[green]✓[/green] Benchmarks completed. Generating release report...\n")
for benchmark_group in type_grouped_benchmarks:
console.print(f"[cyan]Generated for:[/cyan] [bold]{benchmark_group.type_}[/bold]")
console.print(f" [green]✓[/green] {benchmark_group.type_}_comparison.png")
console.print(f" [green]✓[/green] {benchmark_group.type_}.json\n")
console.print(f"[bold green]✓ Release report generated successfully[/bold green]")
console.print(f"[cyan]Output directory:[/cyan] [bold]{output_dir}[/bold]")
@router.command(
@@ -0,0 +1,42 @@
{
"type": "finds_appropriate_handler",
"iterations": 1000,
"gc_disabled": true,
"benchmarks": [
{
"name": "benchmark_simple_command",
"description": "Simple command (no flags)",
"avg_time": 0.0354,
"median_time": 0.0345,
"std_dev": 0.0056
},
{
"name": "benchmark_command_with_flags",
"description": "Command with flags (3 flags)",
"avg_time": 0.0544,
"median_time": 0.0536,
"std_dev": 0.009
},
{
"name": "benchmark_many_commands",
"description": "Many commands (50 commands)",
"avg_time": 1.009,
"median_time": 1.0022,
"std_dev": 0.039
},
{
"name": "benchmark_command_with_many_flags",
"description": "Command with many flags (20 flags)",
"avg_time": 0.131,
"median_time": 0.1298,
"std_dev": 0.0054
},
{
"name": "benchmark_extreme_router",
"description": "Extreme (100 commands, 10 flags each)",
"avg_time": 3.1818,
"median_time": 3.1619,
"std_dev": 0.1673
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

@@ -0,0 +1,70 @@
{
"type": "flag_validation",
"iterations": 1000,
"gc_disabled": true,
"benchmarks": [
{
"name": "benchmark_validate_all_single_flag",
"description": "Single flag with PossibleValues.ALL",
"avg_time": 0.0009,
"median_time": 0.0009,
"std_dev": 0.0003
},
{
"name": "benchmark_validate_neither_single_flag",
"description": "Single flag with PossibleValues.NEITHER",
"avg_time": 0.0008,
"median_time": 0.0008,
"std_dev": 0.0002
},
{
"name": "benchmark_validate_list_small",
"description": "List validation (5 possible values)",
"avg_time": 0.001,
"median_time": 0.001,
"std_dev": 0.0003
},
{
"name": "benchmark_validate_list_large",
"description": "List validation (50 possible values)",
"avg_time": 0.0079,
"median_time": 0.0078,
"std_dev": 0.0007
},
{
"name": "benchmark_validate_regex_simple",
"description": "Regex validation (simple pattern)",
"avg_time": 0.0019,
"median_time": 0.0016,
"std_dev": 0.0073
},
{
"name": "benchmark_validate_regex_complex",
"description": "Regex validation (complex pattern)",
"avg_time": 0.0018,
"median_time": 0.0017,
"std_dev": 0.0051
},
{
"name": "benchmark_validate_multiple_flags_10",
"description": "Multiple flags validation (10 flags)",
"avg_time": 0.0147,
"median_time": 0.0146,
"std_dev": 0.0013
},
{
"name": "benchmark_validate_multiple_flags_50",
"description": "Multiple flags validation (50 flags)",
"avg_time": 0.0669,
"median_time": 0.0661,
"std_dev": 0.0025
},
{
"name": "benchmark_validate_extreme_100_flags",
"description": "Extreme (100 flags with regex validation)",
"avg_time": 0.1626,
"median_time": 0.1609,
"std_dev": 0.007
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

@@ -0,0 +1,56 @@
{
"type": "input_command_parse",
"iterations": 1000,
"gc_disabled": true,
"benchmarks": [
{
"name": "benchmark_parse_simple_command",
"description": "Simple command (no flags)",
"avg_time": 0.0099,
"median_time": 0.0098,
"std_dev": 0.0014
},
{
"name": "benchmark_command_with_few_flags",
"description": "Command with few flags (3 flags)",
"avg_time": 0.0214,
"median_time": 0.0211,
"std_dev": 0.003
},
{
"name": "benchmark_command_with_flags_and_values",
"description": "Command with flags and values (5 flags)",
"avg_time": 0.0598,
"median_time": 0.0591,
"std_dev": 0.0041
},
{
"name": "benchmark_command_with_mixed_prefixes",
"description": "Command with mixed prefixes (-, --, ---)",
"avg_time": 0.0545,
"median_time": 0.0541,
"std_dev": 0.0024
},
{
"name": "benchmark_command_with_long_values",
"description": "Command with long values (10 flags)",
"avg_time": 0.2114,
"median_time": 0.2103,
"std_dev": 0.0068
},
{
"name": "benchmark_command_with_quoted_values",
"description": "Command with quoted values (5 flags)",
"avg_time": 0.0489,
"median_time": 0.0488,
"std_dev": 0.0019
},
{
"name": "benchmark_extreme_many_flags",
"description": "Extreme (50 flags with values)",
"avg_time": 0.8057,
"median_time": 0.7997,
"std_dev": 0.024
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

@@ -0,0 +1,42 @@
{
"type": "most_similar_command",
"iterations": 1000,
"gc_disabled": true,
"benchmarks": [
{
"name": "benchmark_few_commands",
"description": "Few commands (10 commands, no match)",
"avg_time": 0.207,
"median_time": 0.2051,
"std_dev": 0.01
},
{
"name": "benchmark_many_commands_most_similar",
"description": "Many commands (50 commands, no match)",
"avg_time": 1.0116,
"median_time": 1.0074,
"std_dev": 0.0306
},
{
"name": "benchmark_many_aliases",
"description": "Many aliases (20 commands, 10 aliases each)",
"avg_time": 0.6857,
"median_time": 0.6672,
"std_dev": 0.0811
},
{
"name": "benchmark_partial_match",
"description": "Partial match (50 commands, prefix match)",
"avg_time": 1.0218,
"median_time": 1.0192,
"std_dev": 0.0232
},
{
"name": "benchmark_extreme_commands",
"description": "Extreme (100 commands, 20 aliases each)",
"avg_time": 6.4118,
"median_time": 6.4225,
"std_dev": 0.2008
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

@@ -0,0 +1,42 @@
{
"type": "pre_cycle_setup",
"iterations": 1000,
"gc_disabled": true,
"benchmarks": [
{
"name": "benchmark_no_aliases",
"description": "With no aliases",
"avg_time": 8.9994,
"median_time": 8.9559,
"std_dev": 0.242
},
{
"name": "benchmark_few_aliases",
"description": "With few aliases (6 total)",
"avg_time": 8.957,
"median_time": 8.936,
"std_dev": 0.2296
},
{
"name": "benchmark_with_many_aliases",
"description": "With many aliases (15 total)",
"avg_time": 8.9953,
"median_time": 8.9721,
"std_dev": 0.2243
},
{
"name": "benchmark_very_many_aliases",
"description": "With very many aliases (60 total)",
"avg_time": 9.0155,
"median_time": 8.9992,
"std_dev": 0.2433
},
{
"name": "benchmark_extreme_aliases",
"description": "With extreme aliases (300 total)",
"avg_time": 9.2977,
"median_time": 9.255,
"std_dev": 0.3884
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

@@ -0,0 +1,42 @@
{
"type": "validate_routers_for_collisions",
"iterations": 1000,
"gc_disabled": true,
"benchmarks": [
{
"name": "benchmark_few_routers",
"description": "With few routers (3 routers, 1 command each)",
"avg_time": 0.0912,
"median_time": 0.0901,
"std_dev": 0.0051
},
{
"name": "benchmark_many_routers",
"description": "With many routers (10 routers, 1 command each)",
"avg_time": 0.2433,
"median_time": 0.2382,
"std_dev": 0.0292
},
{
"name": "benchmark_many_commands_per_router",
"description": "With many commands per router (3 routers, 10 commands each)",
"avg_time": 0.6157,
"median_time": 0.6132,
"std_dev": 0.0199
},
{
"name": "benchmark_many_aliases_per_command",
"description": "With many aliases (3 routers, 5 commands, 10 aliases each)",
"avg_time": 0.516,
"median_time": 0.5082,
"std_dev": 0.0403
},
{
"name": "benchmark_extreme_routers",
"description": "Extreme (20 routers, 10 commands, 20 aliases each)",
"avg_time": 10.8103,
"median_time": 10.7871,
"std_dev": 0.2788
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

+2 -1
View File
@@ -1,5 +1,6 @@
from .diagram_generator import DiagramGenerator
from .report_generator import ReportGenerator
from .system_info_reader import get_system_info
from .release_generator import ReleaseGenerator
__all__ = ["DiagramGenerator", "ReportGenerator", "get_system_info"]
__all__ = ["DiagramGenerator", "ReportGenerator", "get_system_info", "ReleaseGenerator"]
+49
View File
@@ -0,0 +1,49 @@
__all__ = ["ReleaseGenerator"]
import json
import shutil
from pathlib import Path
from ..benchmarks.core.models import BenchmarkGroupResult
from .diagram_generator import DiagramGenerator
class ReleaseGenerator:
def __init__(self, lib_version: str) -> None:
self.lib_version = lib_version
self.output_dir = Path("metrics/reports/releases") / lib_version
def generate_release(self, benchmark_groups: list[BenchmarkGroupResult]) -> Path:
if self.output_dir.exists():
shutil.rmtree(self.output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
for benchmark_group in benchmark_groups:
type_dir = self.output_dir / benchmark_group.type_
type_dir.mkdir(exist_ok=True)
diagram_generator = DiagramGenerator(type_dir)
diagram_generator.generate_comparison_diagram(benchmark_group)
json_data = {
"type": benchmark_group.type_,
"iterations": benchmark_group.iterations,
"gc_disabled": benchmark_group.is_gc_disabled,
"benchmarks": [
{
"name": br.name,
"description": br.description,
"avg_time": br.avg_time,
"median_time": br.median_time,
"std_dev": br.std_dev
}
for br in benchmark_group.benchmark_results
]
}
json_path = type_dir / f"{benchmark_group.type_}.json"
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(json_data, f, indent=2, ensure_ascii=False)
return self.output_dir