This commit is contained in:
2026-01-17 00:42:00 +03:00
parent 00cb94ffe2
commit 6aa6b0f179
12 changed files with 201 additions and 91 deletions
-1
View File
@@ -1 +0,0 @@
from .benchmarks import *
+8 -41
View File
@@ -1,48 +1,15 @@
from concurrent.futures import ProcessPoolExecutor from argenta import App, Orchestrator
import os from argenta.app import DynamicDividingLine
from rich.console import Console from .handlers import router
from rich.table import Table
from rich.panel import Panel
from rich.text import Text
from metrics.utils import run_benchmark, BenchmarkResult app = App(initial_message="metrics", prompt=">>> ", dividing_line=DynamicDividingLine('~'))
from .registry import Benchmarks, Benchmark orchestrator = Orchestrator()
def main(): def main() -> None:
console = Console() app.include_router(router)
all_benchmarks: list[Benchmark] = Benchmarks.get_benchmarks() orchestrator.start_polling(app)
workers = os.cpu_count() or 1
with ProcessPoolExecutor(max_workers=workers) as executor:
results = executor.map(run_benchmark, all_benchmarks)
type_paired_benchmarks: dict[str, list[BenchmarkResult]] = {}
for result in results:
type_paired_benchmarks.setdefault(result.type_, []).append(result)
for type_, benchmarks in type_paired_benchmarks.items():
header_text = Text(f"TYPE: {type_.upper()}", style="bold magenta")
console.print(Panel(header_text, expand=False, border_style="magenta"))
table = Table(show_header=True, header_style="bold cyan", border_style="blue", show_lines=True)
table.add_column("Name", style="green")
table.add_column("Description", style="dim")
table.add_column("Iterations", justify="right")
table.add_column("Avg Time (ms)", justify="right", style="bold yellow")
for benchmark in benchmarks:
table.add_row(
benchmark.name,
benchmark.description,
str(benchmark.iterations),
str(benchmark.avg_time)
)
console.print(table)
console.print()
if __name__ == "__main__": if __name__ == "__main__":
+1 -1
View File
@@ -1 +1 @@
from .pre_cycle_setup import * from .core import *
+1
View File
@@ -0,0 +1 @@
from .pre_cycle_setup import *
@@ -7,12 +7,12 @@ __all__ = [
] ]
from argenta import App from argenta import App
from argenta.router import Router
from argenta.command.models import Command from argenta.command.models import Command
from argenta.response import Response from argenta.response import Response
from argenta.router import Router
from ..models import benchmark
from ..utils import get_time_of_pre_cycle_setup from ..utils import get_time_of_pre_cycle_setup
from ..registry import benchmark
@benchmark(type_="pre_cycle_setup", description="With no aliases") @benchmark(type_="pre_cycle_setup", description="With no aliases")
@@ -1,14 +1,26 @@
__all__ = [ __all__ = [
"Benchmark", "Benchmark",
"Benchmarks", "Benchmarks",
"BenchmarkResult",
"benchmark" "benchmark"
] ]
from dataclasses import dataclass
from decimal import Decimal
from typing import Callable, ClassVar, overload, override from typing import Callable, ClassVar, overload, override
BenchmarkAsFunc = Callable[[], float] BenchmarkAsFunc = Callable[[], float]
@dataclass(frozen=True)
class BenchmarkResult:
type_: str
name: str
description: str
iterations: int
avg_time: Decimal
class Benchmark: class Benchmark:
def __init__( def __init__(
self, self,
+89
View File
@@ -0,0 +1,89 @@
__all__ = [
"get_time_of_pre_cycle_setup",
"attempts_to_average",
"run_benchmark",
"run_all_benchmarks",
"get_kernel_version"
]
import io
import os
import platform
import sys
import time
from concurrent.futures import ProcessPoolExecutor
from contextlib import redirect_stdout
from decimal import ROUND_HALF_UP, Decimal
from argenta import App
from .models import Benchmark, BenchmarkResult, Benchmarks
def get_time_of_pre_cycle_setup(app: App) -> float:
start = time.perf_counter()
with redirect_stdout(io.StringIO()):
app._pre_cycle_setup() # pyright: ignore[reportPrivateUsage]
end = time.perf_counter()
return (end - start) * 1000 # as milliseconds
def get_kernel_version() -> dict[str, str]:
system = platform.system()
if system == "Windows":
ver = sys.getwindowsversion()
kernel_version = f"{ver.major}.{ver.minor}.{ver.build}"
if ver.build >= 22000:
product_name = "Windows 11"
else:
product_name = "Windows 10"
return {
'kernel_version': kernel_version,
'product_name': product_name
}
elif system == "Linux":
return {
'kernel_version': platform.release(),
'product_name': platform.system()
}
elif system == "Darwin":
return {
'kernel_version': platform.release(),
'product_name': f"macOS {platform.mac_ver()[0]}"
}
else:
return {
'kernel_version': platform.release(),
'product_name': platform.system(),
}
def attempts_to_average(bench_attempts: list[float], iterations: int) -> Decimal:
return Decimal(sum(bench_attempts) / iterations).quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP)
def run_all_benchmarks() -> dict[str, list[BenchmarkResult]]:
all_benchmarks: list[Benchmark] = Benchmarks.get_benchmarks()
workers = os.cpu_count() or 1
with ProcessPoolExecutor(max_workers=workers) as executor:
results = executor.map(run_benchmark, all_benchmarks)
type_paired_benchmarks: dict[str, list[BenchmarkResult]] = {}
for result in results:
type_paired_benchmarks.setdefault(result.type_, []).append(result)
return type_paired_benchmarks
def run_benchmark(benchmark: Benchmark) -> BenchmarkResult:
bench_attempts: list[float] = []
for _ in range(benchmark.iterations):
bench_attempts.append(benchmark.run())
avg = attempts_to_average(bench_attempts, benchmark.iterations)
return BenchmarkResult(benchmark.type_, benchmark.name, benchmark.description, benchmark.iterations, avg)
+70
View File
@@ -0,0 +1,70 @@
import platform
import cpuinfo
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from argenta.command.models import Command
from argenta.response import Response
from argenta.router import Router
from .benchmarks.models import BenchmarkResult
from .benchmarks.utils import run_all_benchmarks, get_kernel_version
console = Console()
router = Router(title="Metrics commands:")
@router.command(Command("all-print", description="Print all benchmarks results"))
def all_print_handler(_: Response) -> None:
cpu_info = cpuinfo.get_cpu_info()
os_info = get_kernel_version()
table = Table(show_header=True, header_style="bold cyan", border_style="blue", show_lines=True)
table.add_column("Parameter", style="green")
table.add_column("Value", style="yellow")
table.add_row("OS", platform.system())
table.add_row("OS Name", os_info['product_name'])
table.add_row("OS Kernel Version", os_info['kernel_version'])
table.add_row("Architecture", cpu_info['arch'])
table.add_row("Processor", cpu_info['brand_raw'])
table.add_row("Python Version", cpu_info['python_version'])
table.add_row("Python Implementation", platform.python_implementation())
header_text = Text("SYSTEM INFO", style="bold magenta")
console.print(Panel(header_text, expand=False, border_style="magenta"))
console.print(table, end="\n\n")
type_paired_benchmarks: dict[str, list[BenchmarkResult]] = run_all_benchmarks()
for type_, benchmarks in type_paired_benchmarks.items():
header_text = Text(f"TYPE: {type_.upper()}", style="bold magenta")
console.print(Panel(header_text, expand=False, border_style="magenta"))
table = Table(show_header=True, header_style="bold cyan", border_style="blue", show_lines=True)
table.add_column("Name", style="green")
table.add_column("Description", style="dim")
table.add_column("Iterations", justify="right")
table.add_column("Avg Time (ms)", justify="right", style="bold yellow")
for benchmark in benchmarks:
table.add_row(
benchmark.name,
benchmark.description,
str(benchmark.iterations),
str(benchmark.avg_time)
)
console.print(table)
@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]")
@router.command(Command("diagrams-generate", description="Generate diagrams"))
def diagrams_generate_handler(_: Response) -> None:
console.print("[yellow]Diagrams generation not implemented yet[/yellow]")
-44
View File
@@ -1,44 +0,0 @@
__all__ = [
"get_time_of_pre_cycle_setup",
"attempts_to_average",
"run_benchmark",
"BenchmarkResult"
]
import io
from contextlib import redirect_stdout
import time
from dataclasses import dataclass
from decimal import Decimal, ROUND_HALF_UP
from argenta import App
from metrics.registry import Benchmark
def get_time_of_pre_cycle_setup(app: App) -> float:
start = time.perf_counter()
with redirect_stdout(io.StringIO()):
app._pre_cycle_setup() # pyright: ignore[reportPrivateUsage]
end = time.perf_counter()
return (end - start) * 1000 # as milliseconds
def attempts_to_average(bench_attempts: list[float], iterations: int) -> Decimal:
return Decimal(sum(bench_attempts) / iterations).quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP)
@dataclass(frozen=True)
class BenchmarkResult:
type_: str
name: str
description: str
iterations: int
avg_time: Decimal
def run_benchmark(benchmark: Benchmark) -> BenchmarkResult:
bench_attempts: list[float] = []
for _ in range(benchmark.iterations):
bench_attempts.append(benchmark.run())
avg = attempts_to_average(bench_attempts, benchmark.iterations)
return BenchmarkResult(benchmark.type_, benchmark.name, benchmark.description, benchmark.iterations, avg)
+3
View File
@@ -35,6 +35,9 @@ tests = [
"pytest-cov>=7.0.0", "pytest-cov>=7.0.0",
"pytest-mock>=3.15.1", "pytest-mock>=3.15.1",
] ]
metrics = [
"py-cpuinfo>=9.0.0",
]
[tool.ruff] [tool.ruff]
exclude = [ exclude = [
+2 -2
View File
@@ -1,6 +1,6 @@
__all__ = ["NonStandardBehaviorHandler", "EmptyCommandHandler", "Printer", "DescriptionMessageGenerator", "HandlerFunc"] __all__ = ["NonStandardBehaviorHandler", "EmptyCommandHandler", "Printer", "DescriptionMessageGenerator", "HandlerFunc"]
from typing import ParamSpec, Protocol, TypeVar from typing import Any, ParamSpec, Protocol, TypeVar
from argenta.response import Response from argenta.response import Response
T = TypeVar("T", contravariant=True) T = TypeVar("T", contravariant=True)
@@ -28,5 +28,5 @@ class DescriptionMessageGenerator(Protocol):
class HandlerFunc(Protocol): class HandlerFunc(Protocol):
def __call__(self, response: Response) -> None: def __call__(self, response: Response, /, *args: Any, **kwargs: Any) -> None:
raise NotImplementedError raise NotImplementedError
Generated
+13
View File
@@ -61,6 +61,9 @@ linters = [
{ name = "ruff" }, { name = "ruff" },
{ name = "wemake-python-styleguide" }, { name = "wemake-python-styleguide" },
] ]
metrics = [
{ name = "py-cpuinfo" },
]
tests = [ tests = [
{ name = "pyfakefs" }, { name = "pyfakefs" },
{ name = "pytest" }, { name = "pytest" },
@@ -92,6 +95,7 @@ linters = [
{ name = "ruff", specifier = ">=0.12.12" }, { name = "ruff", specifier = ">=0.12.12" },
{ name = "wemake-python-styleguide", specifier = ">=0.17.0" }, { name = "wemake-python-styleguide", specifier = ">=0.17.0" },
] ]
metrics = [{ name = "py-cpuinfo", specifier = ">=9.0.0" }]
tests = [ tests = [
{ name = "pyfakefs", specifier = ">=5.5.0" }, { name = "pyfakefs", specifier = ">=5.5.0" },
{ name = "pytest", specifier = ">=8.3.2" }, { name = "pytest", specifier = ">=8.3.2" },
@@ -589,6 +593,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
] ]
[[package]]
name = "py-cpuinfo"
version = "9.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716, upload-time = "2022-10-25T20:38:06.303Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335, upload-time = "2022-10-25T20:38:27.636Z" },
]
[[package]] [[package]]
name = "pycodestyle" name = "pycodestyle"
version = "2.14.0" version = "2.14.0"