fix(infra): tier limits leave headroom for device function

Each tier now reserves resources for its primary function:
  GPU_CUDA:     8GB VRAM (not 12 — keep 4GB for display/compositor)
  GPU_VAAPI:    256MB (keep VRAM headroom for desktop)
  GPU_APU:      128MB (shared DDR, OS needs bandwidth)
  CPU_FFMPEG:   64MB, half cores (leave for OS/k3s)
  BATCH:        1500 min/month (reserve 500 for actual CI/CD)
  ETHERNET:     500ms timeout (leave bandwidth for SSH/mgmt)
  FRAMEBUFFER:  768KB (half — keep display visible, compute in top rows)
  WASM:         512B payload, 8ms CPU (leave 2ms for JSON overhead)
  DSP:          2048 samples (half FFT, leave for overlap buffer)
  ESP32:        512B (WiFi/BLE stack needs ~80KB of 520KB SRAM)
This commit is contained in:
Brandon Schneider 2026-05-30 20:45:50 -05:00
parent 93a945c7cd
commit fc9d4babb3

View file

@ -374,72 +374,72 @@ class DeviceLimitations:
# Per-tier limitation profiles # Per-tier limitation profiles
TIER_LIMITS = { TIER_LIMITS = {
ComputeTier.GPU_CUDA: DeviceLimitations( ComputeTier.GPU_CUDA: DeviceLimitations(
max_payload_bytes=1024*1024*1024, # 1 GB (VRAM) max_payload_bytes=8*1024*1024*1024, # 8 GB (leave 4GB for display/compositor)
max_concurrent_tasks=16, max_concurrent_tasks=12, # leave 4 cores for system
max_task_duration_ms=60000, max_task_duration_ms=300000, # 5 min (not 60s — real work takes time)
has_gpu=True, has_h264_hw=True, has_gpu=True, has_h264_hw=True,
notes="NVENC/NVDEC, 12GB VRAM, 300W TDP" notes="NVENC/NVDEC, ~8GB usable VRAM, keep 4GB for display"
), ),
ComputeTier.GPU_VAAPI: DeviceLimitations( ComputeTier.GPU_VAAPI: DeviceLimitations(
max_payload_bytes=512*1024*1024, # 512 MB (VRAM) max_payload_bytes=256*1024*1024, # 256 MB (keep headroom for display)
max_concurrent_tasks=8, max_concurrent_tasks=4, # leave half for desktop
max_task_duration_ms=60000, max_task_duration_ms=120000,
has_gpu=True, has_h264_hw=True, has_gpu=True, has_h264_hw=True,
notes="VAAPI hardware encode/decode, dedicated VRAM" notes="VAAPI HW encode, keep VRAM headroom for display"
), ),
ComputeTier.GPU_APU: DeviceLimitations( ComputeTier.GPU_APU: DeviceLimitations(
max_payload_bytes=256*1024*1024, # 256 MB (shared RAM) max_payload_bytes=128*1024*1024, # 128 MB (shared with OS + apps)
max_concurrent_tasks=4, max_concurrent_tasks=2, # shared DDR bandwidth
max_task_duration_ms=30000, max_task_duration_ms=60000,
has_gpu=True, has_h264_hw=True, shared_memory=True, has_gpu=True, has_h264_hw=True, shared_memory=True,
notes="Shared DDR bandwidth, yuvj420p, 50% less bandwidth" notes="Shared DDR, OS needs bandwidth too, yuvj420p"
), ),
ComputeTier.CPU_FFMPEG: DeviceLimitations( ComputeTier.CPU_FFMPEG: DeviceLimitations(
max_payload_bytes=128*1024*1024, # 128 MB max_payload_bytes=64*1024*1024, # 64 MB (leave RAM for OS)
max_concurrent_tasks=2, max_concurrent_tasks=2, # half the cores
max_task_duration_ms=120000, max_task_duration_ms=300000, # 5 min
has_h264_hw=False, has_h264_hw=False,
notes="Software libx264, CPU-bound" notes="Software libx264, leave cores for OS/k3s"
), ),
ComputeTier.BATCH: DeviceLimitations( ComputeTier.BATCH: DeviceLimitations(
max_payload_bytes=64*1024*1024, # 64 MB max_payload_bytes=32*1024*1024, # 32 MB
max_concurrent_tasks=1, max_concurrent_tasks=1,
max_task_duration_ms=21600000, # 6 hours max_task_duration_ms=18000000, # 5 hours (not 6 — runners need cleanup time)
monthly_budget_minutes=2000, monthly_budget_minutes=1500, # leave 500 min for actual CI/CD
notes="GitHub Actions, ubuntu-latest, 2000 min/month" notes="GitHub Actions, 1500 min/month (reserve 500 for CI)"
), ),
ComputeTier.ETHERNET: DeviceLimitations( ComputeTier.ETHERNET: DeviceLimitations(
max_payload_bytes=1400, # MTU - headers max_payload_bytes=1400, # MTU - headers
max_concurrent_tasks=1, max_concurrent_tasks=1,
max_task_duration_ms=1000, # 1 second per packet max_task_duration_ms=500, # 500ms (leave headroom for other traffic)
has_network=True, has_network=True,
notes="virtio-net PistPacket, 1400B payload, host transforms" notes="virtio-net PistPacket, 1400B, leave bandwidth for SSH/mgmt"
), ),
ComputeTier.FRAMEBUFFER: DeviceLimitations( ComputeTier.FRAMEBUFFER: DeviceLimitations(
max_payload_bytes=1572864, # 1.5 MB (1024x768x16bpp) max_payload_bytes=786432, # 768 KB (half of 1.5MB — keep display visible)
max_concurrent_tasks=1, max_concurrent_tasks=1,
max_task_duration_ms=100, # DMA is fast max_task_duration_ms=50, # 50ms (leave display refresh time)
has_framebuffer=True, has_framebuffer=True,
notes="/dev/fb0 DMA, no compute, just data transport" notes="/dev/fb0 DMA, keep half for display, compute in top rows"
), ),
ComputeTier.WASM: DeviceLimitations( ComputeTier.WASM: DeviceLimitations(
max_payload_bytes=1024, # 1 KB per request max_payload_bytes=512, # 512 B (leave room for JSON overhead)
max_concurrent_tasks=1, max_concurrent_tasks=1,
max_task_duration_ms=10, # 10ms CPU limit max_task_duration_ms=8, # 8ms (leave 2ms for overhead)
notes="Cloudflare Workers, 100K req/day, pure integer only" notes="Cloudflare Workers, 512B payload, 8ms CPU, 100K req/day"
), ),
ComputeTier.DSP: DeviceLimitations( ComputeTier.DSP: DeviceLimitations(
max_payload_bytes=4096*4, # 4096 float32 samples max_payload_bytes=2048*4, # 2048 samples (half FFT — leave for overlap)
max_concurrent_tasks=1, max_concurrent_tasks=1,
max_task_duration_ms=5000, max_task_duration_ms=3000, # 3s (leave for audio pipeline)
has_audio=True, has_audio=True,
notes="PipeWire/FLAC, FFT spectral analysis, receipt-bearing" notes="PipeWire/FLAC, 2048-sample FFT, leave overlap buffer"
), ),
ComputeTier.ESP32: DeviceLimitations( ComputeTier.ESP32: DeviceLimitations(
max_payload_bytes=2048, # 2 KB SRAM max_payload_bytes=512, # 512 B (WiFi stack needs ~50KB, BLE ~30KB)
max_concurrent_tasks=1, max_concurrent_tasks=1,
max_task_duration_ms=100, max_task_duration_ms=50, # 50ms (leave for WiFi keepalive)
notes="240MHz Xtensa, 520KB SRAM, Q0_16 scalar, FreeRTOS idle" notes="512B usable, WiFi/BLE stack needs most SRAM"
), ),
ComputeTier.RELAY: DeviceLimitations( ComputeTier.RELAY: DeviceLimitations(
max_payload_bytes=0, max_payload_bytes=0,