refactor(webui): redesign Burn tab and fix gpu-burn memory defaults

- Burn tab: replace 6 flat cards with 3 grouped cards (GPU Stress,
  Compute Stress, Platform Thermal Cycling) + global Burn Profile
- Run All button at top enqueues all enabled tests across all cards
- GPU Stress: tool checkboxes enabled/disabled via new /api/gpu/tools
  endpoint based on driver status (/dev/nvidia0, /dev/kfd)
- Compute Stress: checkboxes for cpu/memory-stress/stressapptest
- Platform Thermal Cycling: component checkboxes (cpu/nvidia/amd)
  with platform_components param wired through to PlatformStressOptions
- bee-gpu-burn: default size-mb changed from 64 to 0 (auto); script
  now queries nvidia-smi memory.total per GPU and uses 95% of it
- platform_stress: removed hardcoded --size-mb 64; respects Components
  field to selectively run CPU and/or GPU load goroutines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-04-01 09:39:07 +03:00
parent 5839f870b7
commit 4e4debd4da
7 changed files with 312 additions and 125 deletions

View File

@@ -255,8 +255,9 @@ func NewHandler(opts HandlerOptions) http.Handler {
mux.HandleFunc("GET /api/display/resolutions", h.handleAPIDisplayResolutions)
mux.HandleFunc("POST /api/display/set", h.handleAPIDisplaySet)
// GPU presence
// GPU presence / tools
mux.HandleFunc("GET /api/gpu/presence", h.handleAPIGPUPresence)
mux.HandleFunc("GET /api/gpu/tools", h.handleAPIGPUTools)
// System
mux.HandleFunc("GET /api/system/ram-status", h.handleAPIRAMStatus)
@@ -516,6 +517,7 @@ func (h *handler) handleMetricsChartSVG(w http.ResponseWriter, r *http.Request)
case path == "server-power":
title = "System Power"
vPower, l := h.ringPower.snapshot()
vPower = normalizePowerSeries(vPower)
labels = l
datasets = [][]float64{vPower}
names = []string{"Power W"}
@@ -728,9 +730,11 @@ func chartDataFromSamples(path string, samples []platform.LiveMetricSample) ([][
for i, s := range samples {
power[i] = s.PowerW
}
power = normalizePowerSeries(power)
datasets = [][]float64{power}
names = []string{"Power W"}
yMin, yMax = autoBounds120(power)
yMin = floatPtr(0)
yMax = autoMax120(power)
case path == "server-fans":
title = "Fan RPM"
@@ -928,6 +932,27 @@ func coalesceDataset(ds []float64, n int) []float64 {
return make([]float64, n)
}
func normalizePowerSeries(ds []float64) []float64 {
if len(ds) == 0 {
return nil
}
out := make([]float64, len(ds))
copy(out, ds)
last := 0.0
haveLast := false
for i, v := range out {
if v > 0 {
last = v
haveLast = true
continue
}
if haveLast {
out[i] = last
}
}
return out
}
// floatPtr returns a pointer to a float64 value.
func floatPtr(v float64) *float64 { return &v }