package webui import ( "encoding/json" "fmt" "html" "os" "path/filepath" "sort" "strconv" "strings" "time" "bee/audit/internal/app" "bee/audit/internal/platform" ) type benchmarkHistoryRun struct { generatedAt time.Time displayTime string gpuScores map[int]float64 gpuStatuses map[int]string overallStatus string } func renderBenchmark(opts HandlerOptions) string { return `

Benchmark runs generate a human-readable TXT report and machine-readable result bundle. Tasks continue in the background — view progress in Tasks.

Benchmark Setup

Loading NVIDIA GPUs...

Select one GPU for single-card benchmarking or several GPUs for a constrained multi-GPU run.

Autotune status: loading…
Autotune overwrites the saved system-power source and applies it to all new power charts and tests.
Method Split

The benchmark page now exposes two fundamentally different test families so compute score and server power-fit are not mixed into one number.

Run TypeEngineQuestionStandardStability
Performance Benchmarkbee-gpu-burnHow much isolated compute performance does the GPU realize in this server?` + validateFmtDur(platform.BenchmarkEstimatedPerfStandardSec) + `` + validateFmtDur(platform.BenchmarkEstimatedPerfStabilitySec) + `
Power / Thermal Fitdcgmproftester + nvidia-smi -plHow much power per GPU can this server sustain as GPU count ramps up?` + validateFmtDur(platform.BenchmarkEstimatedPowerStandardSec) + `` + validateFmtDur(platform.BenchmarkEstimatedPowerStabilitySec) + `

Timings are per full ramp-up run (1 GPU → all selected), measured on 4–8 GPU servers. Use ramp-up mode for capacity work: it creates 1 GPU → 2 GPU → … → all selected steps so analysis software can derive server total score and watts-per-GPU curves.

` + `
` + renderBenchmarkResultsCard(opts.ExportDir) + `
` + ` ` } func renderBenchmarkResultsCard(exportDir string) string { maxIdx, runs := loadBenchmarkHistory(exportDir) perf := renderBenchmarkResultsCardFromRuns( "Perf Results", "Composite score by saved benchmark run and GPU.", "No saved performance benchmark runs yet.", maxIdx, runs, ) power := renderPowerBenchmarkResultsCard(exportDir) return perf + "\n" + power } func renderBenchmarkResultsCardFromRuns(title, description, emptyMessage string, maxGPUIndex int, runs []benchmarkHistoryRun) string { if len(runs) == 0 { return `
` + html.EscapeString(title) + `

` + html.EscapeString(emptyMessage) + `

` } var b strings.Builder b.WriteString(`
` + html.EscapeString(title) + `
`) if strings.TrimSpace(description) != "" { b.WriteString(`

` + html.EscapeString(description) + `

`) } b.WriteString(`
`) b.WriteString(``) for i := 0; i <= maxGPUIndex; i++ { b.WriteString(``) } b.WriteString(``) for i, run := range runs { b.WriteString(``) b.WriteString(``) b.WriteString(``) overallColor := "var(--ok)" overallLabel := run.overallStatus if overallLabel == "" { overallLabel = "OK" } if overallLabel == "FAILED" { overallColor = "var(--crit-fg,#9f3a38)" } else if overallLabel != "OK" { overallColor = "var(--warn)" } b.WriteString(``) for idx := 0; idx <= maxGPUIndex; idx++ { score, ok := run.gpuScores[idx] if !ok { b.WriteString(``) continue } gpuStatus := run.gpuStatuses[idx] scoreColor := "" switch gpuStatus { case "FAILED": scoreColor = ` style="color:var(--crit-fg,#9f3a38);font-weight:600"` case "WARNING", "PARTIAL": scoreColor = ` style="color:var(--warn);font-weight:600"` case "", "OK": default: scoreColor = ` style="color:var(--warn);font-weight:600"` } b.WriteString(`` + fmt.Sprintf("%.2f", score) + ``) } b.WriteString(``) } b.WriteString(`
RunTimeStatusGPU ` + strconv.Itoa(i) + `
#` + strconv.Itoa(i+1) + `` + html.EscapeString(run.displayTime) + `` + html.EscapeString(overallLabel) + `-
`) return b.String() } func loadBenchmarkHistory(exportDir string) (int, []benchmarkHistoryRun) { baseDir := app.DefaultBeeBenchPerfDir if strings.TrimSpace(exportDir) != "" { baseDir = filepath.Join(exportDir, "bee-bench", "perf") } paths, err := filepath.Glob(filepath.Join(baseDir, "perf-*", "result.json")) if err != nil || len(paths) == 0 { return -1, nil } sort.Strings(paths) return loadBenchmarkHistoryFromPaths(paths) } func loadBenchmarkHistoryFromPaths(paths []string) (int, []benchmarkHistoryRun) { runs := make([]benchmarkHistoryRun, 0, len(paths)) maxGPUIndex := -1 for _, path := range paths { raw, err := os.ReadFile(path) if err != nil { continue } var result platform.NvidiaBenchmarkResult if err := json.Unmarshal(raw, &result); err != nil { continue } run := benchmarkHistoryRun{ generatedAt: result.GeneratedAt, displayTime: result.GeneratedAt.Local().Format("2006-01-02 15:04:05"), gpuScores: make(map[int]float64), gpuStatuses: make(map[int]string), overallStatus: result.OverallStatus, } for _, gpu := range result.GPUs { run.gpuScores[gpu.Index] = gpu.Scores.CompositeScore run.gpuStatuses[gpu.Index] = gpu.Status if gpu.Index > maxGPUIndex { maxGPUIndex = gpu.Index } } runs = append(runs, run) } sort.Slice(runs, func(i, j int) bool { return runs[i].generatedAt.After(runs[j].generatedAt) }) return maxGPUIndex, runs } func renderPowerBenchmarkResultsCard(exportDir string) string { baseDir := app.DefaultBeeBenchPowerDir if strings.TrimSpace(exportDir) != "" { baseDir = filepath.Join(exportDir, "bee-bench", "power") } paths, err := filepath.Glob(filepath.Join(baseDir, "power-*", "result.json")) if err != nil || len(paths) == 0 { return `
Power / Thermal Fit Results

No saved power benchmark runs yet.

` } sort.Strings(paths) type powerRun struct { generatedAt time.Time displayTime string result platform.NvidiaPowerBenchResult } var runs []powerRun for _, path := range paths { raw, err := os.ReadFile(path) if err != nil { continue } var r platform.NvidiaPowerBenchResult if err := json.Unmarshal(raw, &r); err != nil { continue } runs = append(runs, powerRun{ generatedAt: r.GeneratedAt, displayTime: r.GeneratedAt.Local().Format("2006-01-02 15:04:05"), result: r, }) } sort.Slice(runs, func(i, j int) bool { return runs[i].generatedAt.After(runs[j].generatedAt) }) var b strings.Builder b.WriteString(`
Power / Thermal Fit Results
`) latest := runs[0].result b.WriteString(`

Latest run: ` + html.EscapeString(runs[0].displayTime)) if latest.Hostname != "" { b.WriteString(` — ` + html.EscapeString(latest.Hostname)) } if latest.OverallStatus != "" { statusColor := "var(--ok)" if latest.OverallStatus != "OK" { statusColor = "var(--warn)" } b.WriteString(` — ` + html.EscapeString(latest.OverallStatus) + ``) } b.WriteString(`

`) if len(latest.GPUs) > 0 { b.WriteString(`
`) b.WriteString(``) b.WriteString(``) for _, gpu := range latest.GPUs { finalLimitW := gpu.StablePowerLimitW if finalLimitW <= 0 { finalLimitW = gpu.AppliedPowerLimitW } derated := gpu.Derated || (gpu.DefaultPowerLimitW > 0 && finalLimitW > 0 && finalLimitW < gpu.DefaultPowerLimitW-1) rowStyle := "" finalStyle := "" if derated { rowStyle = ` style="background:rgba(255,180,0,0.08)"` finalStyle = ` style="color:#e6a000;font-weight:600"` } statusLabel := gpu.Status if statusLabel == "" { statusLabel = "OK" } statusColor := "var(--ok)" if statusLabel == "FAILED" { statusColor = "var(--crit-fg,#9f3a38)" } else if statusLabel != "OK" { statusColor = "var(--warn)" } nominalStr := "-" if gpu.DefaultPowerLimitW > 0 { nominalStr = fmt.Sprintf("%.0f", gpu.DefaultPowerLimitW) } singleStr := "-" if gpu.AppliedPowerLimitW > 0 { singleStr = fmt.Sprintf("%.0f", gpu.AppliedPowerLimitW) } multiStr := "-" if gpu.StablePowerLimitW > 0 { multiStr = fmt.Sprintf("%.0f", gpu.StablePowerLimitW) } p95Str := "-" if gpu.MaxObservedPowerW > 0 { p95Str = fmt.Sprintf("%.0f", gpu.MaxObservedPowerW) } b.WriteString(``) b.WriteString(``) b.WriteString(``) b.WriteString(``) b.WriteString(``) b.WriteString(`` + multiStr + ``) b.WriteString(``) b.WriteString(``) b.WriteString(``) } b.WriteString(`
GPUModelNominal WSingle-card WMulti-GPU WP95 Observed WStatus
` + strconv.Itoa(gpu.Index) + `` + html.EscapeString(gpu.Name) + `` + nominalStr + `` + singleStr + `` + p95Str + `` + html.EscapeString(statusLabel) + `
`) } if len(runs) > 1 { b.WriteString(`
` + strconv.Itoa(len(runs)) + ` runs total`) b.WriteString(`
`) for i, run := range runs { statusColor := "var(--ok)" if run.result.OverallStatus != "OK" { statusColor = "var(--warn)" } b.WriteString(``) b.WriteString(``) b.WriteString(``) b.WriteString(``) b.WriteString(``) b.WriteString(``) } b.WriteString(`
#TimeGPUsStatus
#` + strconv.Itoa(i+1) + `` + html.EscapeString(run.displayTime) + `` + strconv.Itoa(len(run.result.GPUs)) + `` + html.EscapeString(run.result.OverallStatus) + `
`) } b.WriteString(`
`) return b.String() } // renderSpeed renders the Speed page (step 4): performance benchmarks. // Uses the same benchmark infrastructure; defaults to Standard profile (throughput/bandwidth). // For long-duration stability/overnight runs, see Endurance (step 5). func renderSpeed(opts HandlerOptions) string { base := renderBenchmark(opts) return `
Speed: Measures GPU compute throughput and memory bandwidth. For overnight stability testing, go to 5. Endurance.
` + base } // renderEndurance renders the Endurance page (step 5): long-duration reliability tests. // Focuses on Stability and Overnight profiles for multi-hour burn validation. // For short load tests, see Load (step 3). For throughput measurement, see Speed (step 4). func renderEndurance(opts HandlerOptions) string { base := renderBenchmark(opts) return `
Endurance: Long-duration reliability tests — Stability (several hours) and Overnight (8+ h) profiles. These profiles run hardware at sustained load; results show whether the server holds its performance envelope over time.
Use the Stability or Overnight profile in the setup card below. The Standard profile is available too but is better suited for the 4. Speed page.
` + base }