This commit is contained in:
Gilles Soulier
2026-01-05 16:08:01 +01:00
parent dcba044cd6
commit c67befc549
2215 changed files with 26743 additions and 329 deletions

65
backend/app/utils/scoring.py Normal file → Executable file
View File

@@ -1,12 +1,12 @@
"""
Linux BenchTools - Scoring Utilities
New normalized scoring formulas (0-100 scale):
- CPU: events_per_second / 100
- Memory: throughput_mib_s / 1000
- Disk: (read_mb_s + write_mb_s) / 20
- Network: (upload_mbps + download_mbps) / 20
- GPU: glmark2_score / 50
Raw benchmark scoring (no normalization):
- CPU: events_per_second (raw)
- Memory: throughput_mib_s (raw)
- Disk: read_mb_s + write_mb_s (raw)
- Network: upload_mbps + download_mbps (raw)
- GPU: glmark2_score (raw)
"""
from app.core.config import settings
@@ -16,42 +16,40 @@ def calculate_cpu_score(events_per_second: float = None) -> float:
"""
Calculate CPU score from sysbench events per second.
Formula: events_per_second / 100
Range: 0-100 (capped)
Formula: events_per_second (raw value)
No normalization applied.
Example: 3409.87 events/s → 34.1 score
Example: 3409.87 events/s → 3409.87 score
"""
if events_per_second is None or events_per_second <= 0:
return 0.0
score = events_per_second / 100.0
return min(100.0, max(0.0, score))
return max(0.0, events_per_second)
def calculate_memory_score(throughput_mib_s: float = None) -> float:
"""
Calculate Memory score from sysbench throughput.
Formula: throughput_mib_s / 1000
Range: 0-100 (capped)
Formula: throughput_mib_s (raw value)
No normalization applied.
Example: 13806.03 MiB/s → 13.8 score
Example: 13806.03 MiB/s → 13806.03 score
"""
if throughput_mib_s is None or throughput_mib_s <= 0:
return 0.0
score = throughput_mib_s / 1000.0
return min(100.0, max(0.0, score))
return max(0.0, throughput_mib_s)
def calculate_disk_score(read_mb_s: float = None, write_mb_s: float = None) -> float:
"""
Calculate Disk score from fio read/write bandwidth.
Formula: (read_mb_s + write_mb_s) / 20
Range: 0-100 (capped)
Formula: read_mb_s + write_mb_s (raw value)
No normalization applied.
Example: (695 + 695) MB/s → 69.5 score
Example: (695 + 695) MB/s → 1390 score
"""
if read_mb_s is None and write_mb_s is None:
return 0.0
@@ -59,18 +57,17 @@ def calculate_disk_score(read_mb_s: float = None, write_mb_s: float = None) -> f
read = read_mb_s if read_mb_s is not None and read_mb_s > 0 else 0.0
write = write_mb_s if write_mb_s is not None and write_mb_s > 0 else 0.0
score = (read + write) / 20.0
return min(100.0, max(0.0, score))
return max(0.0, read + write)
def calculate_network_score(upload_mbps: float = None, download_mbps: float = None) -> float:
"""
Calculate Network score from iperf3 upload/download speeds.
Formula: (upload_mbps + download_mbps) / 20
Range: 0-100 (capped)
Formula: upload_mbps + download_mbps (raw value)
No normalization applied.
Example: (484.67 + 390.13) Mbps → 43.7 score
Example: (484.67 + 390.13) Mbps → 874.8 score
"""
if upload_mbps is None and download_mbps is None:
return 0.0
@@ -78,24 +75,22 @@ def calculate_network_score(upload_mbps: float = None, download_mbps: float = No
upload = upload_mbps if upload_mbps is not None and upload_mbps > 0 else 0.0
download = download_mbps if download_mbps is not None and download_mbps > 0 else 0.0
score = (upload + download) / 20.0
return min(100.0, max(0.0, score))
return max(0.0, upload + download)
def calculate_gpu_score(glmark2_score: int = None) -> float:
"""
Calculate GPU score from glmark2 benchmark.
Formula: glmark2_score / 50
Range: 0-100 (capped)
Formula: glmark2_score (raw value)
No normalization applied.
Example: 2500 glmark2 → 50.0 score
Example: 2500 glmark2 → 2500 score
"""
if glmark2_score is None or glmark2_score <= 0:
return 0.0
score = glmark2_score / 50.0
return min(100.0, max(0.0, score))
return max(0.0, float(glmark2_score))
def calculate_global_score(
@@ -146,8 +141,8 @@ def calculate_global_score(
weighted_sum = sum(score * weight for score, weight in zip(scores, weights))
global_score = weighted_sum / total_weight
# Clamp to 0-100 range
return max(0.0, min(100.0, global_score))
# Ensure non-negative
return max(0.0, global_score)
def validate_score(score: float) -> bool:
@@ -158,9 +153,9 @@ def validate_score(score: float) -> bool:
score: Score value to validate
Returns:
bool: True if score is valid (0-100 or None)
bool: True if score is valid (>= 0 or None)
"""
if score is None:
return True
return 0.0 <= score <= 100.0
return score >= 0.0