This commit is contained in:
2026-01-18 23:53:52 +03:00
parent e7d064908f
commit 9d250fde9c
5 changed files with 158 additions and 168 deletions
+73
View File
@@ -0,0 +1,73 @@
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from ..benchmarks.core.models import BenchmarkGroupResult
from metrics.services.system_info_reader import SystemInfo
class ReportGenerator:
def __init__(self, system_info: SystemInfo):
self.system_info = system_info
self._cached_benchmark_tables: dict[int, Table] = {}
self._cached_system_info_table: Table | None = None
def generate_benchmark_report_table(self, benchmark_group_result: BenchmarkGroupResult) -> Table:
if cached_result := self._cached_benchmark_tables.get(id(benchmark_group_result)):
return cached_result
table = Table(show_header=True, header_style="bold cyan", border_style="blue", show_lines=True)
table.add_column("Description", style="dim")
table.add_column("Avg Time", justify="right", style="bold yellow")
table.add_column("Median Time", justify="right", style="bold yellow")
table.add_column("Stdev", justify="right", style="bold yellow")
for benchmark in benchmark_group_result.benchmark_results:
table.add_row(
benchmark.description,
str(benchmark.avg_time),
str(benchmark.median_time),
str(benchmark.std_dev),
)
self._cached_benchmark_tables[id(benchmark_group_result)] = table
return table
@staticmethod
def generate_benchmark_table_header(benchmark_group_result: BenchmarkGroupResult) -> Panel:
header_text = Text(f"TYPE: {benchmark_group_result.type_.upper()} ; "
f"ITERATIONS: {benchmark_group_result.iterations} ; "
f"ALL TIME IN MS",
style="bold magenta")
return Panel(header_text, expand=False, border_style="magenta")
def generate_system_info_table(self) -> Table:
if self._cached_system_info_table is not None:
return self._cached_system_info_table
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 Name", self.system_info.os_info.name)
table.add_row("OS Kernel Version", self.system_info.os_info.kernel_version)
table.add_row("Architecture", self.system_info.cpu_info.architecture)
table.add_row("CPU", self.system_info.cpu_info.name)
table.add_row("CPU Physical Cores", str(self.system_info.cpu_info.physical_cores))
table.add_row("CPU Logical Cores", str(self.system_info.cpu_info.logical_cores))
table.add_row("CPU Max Frequency", str(self.system_info.cpu_info.max_frequency) + ' GHz')
table.add_row("CPU Min Frequency", str(self.system_info.cpu_info.min_frequency) + ' GHz')
table.add_row("CPU Current Frequency", str(self.system_info.cpu_info.current_frequency) + ' GHz')
table.add_row("Total RAM", str(self.system_info.memory_info.total_ram) + ' GB')
table.add_row("Used RAM", str(self.system_info.memory_info.used_ram) + ' GB')
table.add_row("Available RAM", str(self.system_info.memory_info.available_ram) + ' GB')
table.add_row("Python Version", self.system_info.python_info.version)
table.add_row("Python Implementation", self.system_info.python_info.implementation)
table.add_row("Python Compiler", self.system_info.python_info.compiler)
self._cached_system_info_table = table
return table
@staticmethod
def generate_system_info_header() -> Panel:
header_text = Text("SYSTEM INFO", style="bold magenta")
return Panel(header_text, expand=False, border_style="magenta")
+69 -51
View File
@@ -1,13 +1,11 @@
__all__ = [
"SystemInfo",
"SystemInfoGetter",
"get_system_info"
]
from dataclasses import dataclass
import platform
import sys
from typing import Protocol
import cpuinfo
import psutil
@@ -18,72 +16,46 @@ class SystemInfo:
os_info: OSInfo
cpu_info: CPUInfo
memory_info: MemoryInfo
python_version: str
python_implementation: str
python_info: PythonInfo
@dataclass(frozen=True, slots=True)
class OSInfo:
os_name: str
name: str
kernel_version: str
@dataclass(frozen=True, slots=True)
class CPUInfo:
cpu_name: str
cpu_architecture: str
cpu_physical_cores: int
cpu_logical_cores: int
cpu_max_frequency: float
cpu_base_frequency: float
name: str
architecture: str
physical_cores: int
logical_cores: int
max_frequency: float
min_frequency: float
current_frequency: float
@dataclass(frozen=True, slots=True)
class MemoryInfo:
total_ram: float # in GB
used_ram: float # in GB
available_ram: float # in GB
l1_cache: float
l2_cache: float
l3_cache: float
@dataclass(frozen=True, slots=True)
class PythonInfo:
python_version: str
python_implementation: str
python_compiler: str
class SystemInfoGetter(Protocol):
def __call__(self) -> SystemInfo:
raise NotImplementedError
version: str
implementation: str
compiler: str
def get_system_info() -> SystemInfo:
os_info = get_os_info()
os_name = os_info.os_name
os_kernel_version = os_info.kernel_version
cpu_info = cpuinfo.get_cpu_info()
cpu_architecture = cpu_info["arch"]
cpu_name = cpu_info["brand_raw"]
gpu_name = get_gpu_name()
total_ram = psutil.virtual_memory().total / (1024 ** 3)
python_version = platform.python_version()
python_implementation = platform.python_implementation()
cpu_info = get_cpu_info()
memory_info = get_memory_info()
python_info = get_python_info()
return SystemInfo(
os_name=os_name,
kernel_version=os_kernel_version,
cpu_architecture=cpu_architecture,
cpu_name=cpu_name,
gpu_name=gpu_name,
total_ram=total_ram,
python_version=python_version,
python_implementation=python_implementation,
os_info=os_info,
cpu_info=cpu_info,
memory_info=memory_info,
python_info=python_info,
)
def get_os_info() -> OSInfo:
@@ -99,16 +71,62 @@ def get_os_info() -> OSInfo:
product_name = "Windows 10"
return OSInfo(
os_name=product_name,
name=product_name,
kernel_version=kernel_version,
)
elif system == "Darwin":
return OSInfo(
kernel_version=platform.release(),
os_name=f"macOS {platform.mac_ver()[0]}"
name=f"macOS {platform.mac_ver()[0]}"
)
else:
return OSInfo(
kernel_version=platform.release(),
os_name=platform.system()
name=platform.system()
)
def get_cpu_info() -> CPUInfo:
cpu_info = cpuinfo.get_cpu_info()
cpu_name = cpu_info["brand_raw"]
cpu_architecture = cpu_info["arch"]
cpu_physical_cores = psutil.cpu_count(logical=False)
cpu_logical_cores = psutil.cpu_count(logical=True)
cpu_freq = psutil.cpu_freq() or "N/A"
cpu_current_frequency = cpu_freq.current
cpu_min_frequency = cpu_freq.min
cpu_max_frequency = cpu_freq.max
return CPUInfo(
name=cpu_name,
architecture=cpu_architecture,
physical_cores=cpu_physical_cores,
logical_cores=cpu_logical_cores,
current_frequency=cpu_current_frequency,
min_frequency=cpu_min_frequency,
max_frequency=cpu_max_frequency
)
def get_memory_info() -> MemoryInfo:
mem = psutil.virtual_memory()
total_ram = round(mem.total / (1024**3), 2)
used_ram = round(mem.used / (1024**3), 2)
available_ram = round(mem.available / (1024**3), 2)
return MemoryInfo(
total_ram=total_ram,
used_ram=used_ram,
available_ram=available_ram,
)
def get_python_info() -> PythonInfo:
python_version = platform.python_version()
python_implementation = platform.python_implementation()
python_compiler = platform.python_compiler()
return PythonInfo(
version=python_version,
implementation=python_implementation,
compiler=python_compiler
)