Spaces:
Running
Running
GitHub Actions commited on
Commit ·
ba19f79
1
Parent(s): fad27cb
sync from abhijitramesh/webgpu-bench@d153630008
Browse files- js/run/device.js +45 -8
js/run/device.js
CHANGED
|
@@ -84,6 +84,13 @@ const MOBILE_PROBE_TIMEOUT_MS = 10_000;
|
|
| 84 |
const MOBILE_PROBE_YIELD_MS = 50;
|
| 85 |
const MOBILE_PROBE_SAFETY_MARGIN_MB = 150;
|
| 86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
// Probe ceiling per family × maxBufferSize tier. Caps are deliberately
|
| 88 |
// conservative — a probe that completes successfully gives `cap - margin`,
|
| 89 |
// while a probe that OOMs partway gives `probed - margin`. We never
|
|
@@ -348,17 +355,47 @@ async function _computeBudget() {
|
|
| 348 |
}
|
| 349 |
|
| 350 |
const probeCap = getMobileProbeCapMB(mobileFamily, maxBufferSizeMB);
|
| 351 |
-
const
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
|
| 358 |
const margined = gpuProbe.probedMB - MOBILE_PROBE_SAFETY_MARGIN_MB;
|
| 359 |
let gpuBudgetMB;
|
| 360 |
let source;
|
| 361 |
-
if (
|
|
|
|
|
|
|
|
|
|
| 362 |
gpuBudgetMB = margined;
|
| 363 |
const hitCap = gpuProbe.probedMB + MOBILE_PROBE_STEP_MB > probeCap;
|
| 364 |
const detail = hitCap
|
|
@@ -389,7 +426,7 @@ async function _computeBudget() {
|
|
| 389 |
probedMB: 0,
|
| 390 |
gpuProbedMB: gpuProbe.probedMB,
|
| 391 |
probeError: 'skipped on mobile (heap probe can trip Jetsam)',
|
| 392 |
-
gpuProbeError: gpuProbe.error || null,
|
| 393 |
isMobile: true,
|
| 394 |
mobileFamily,
|
| 395 |
source: source + adapterDetail,
|
|
|
|
| 84 |
const MOBILE_PROBE_YIELD_MS = 50;
|
| 85 |
const MOBILE_PROBE_SAFETY_MARGIN_MB = 150;
|
| 86 |
|
| 87 |
+
// SessionStorage sentinel: written before the probe, cleared after. If
|
| 88 |
+
// we see it on the next page load, the previous probe crashed the tab —
|
| 89 |
+
// skip probing and use the static fallback so we don't loop forever
|
| 90 |
+
// with the user staring at a tab that keeps reloading. Cleared at end
|
| 91 |
+
// of probe so subsequent loads in the same session re-probe normally.
|
| 92 |
+
const MOBILE_PROBE_SENTINEL_KEY = 'webgpu-bench:mobile-gpu-probe-in-progress';
|
| 93 |
+
|
| 94 |
// Probe ceiling per family × maxBufferSize tier. Caps are deliberately
|
| 95 |
// conservative — a probe that completes successfully gives `cap - margin`,
|
| 96 |
// while a probe that OOMs partway gives `probed - margin`. We never
|
|
|
|
| 355 |
}
|
| 356 |
|
| 357 |
const probeCap = getMobileProbeCapMB(mobileFamily, maxBufferSizeMB);
|
| 358 |
+
const probeBestCase = probeCap - MOBILE_PROBE_SAFETY_MARGIN_MB;
|
| 359 |
+
|
| 360 |
+
// Skip the probe if even a successful run can't beat the static
|
| 361 |
+
// fallback — allocating ~probeCap of GPU buffers on a low-RAM iPhone
|
| 362 |
+
// (e.g. iPhone 13 with 6 GB) can itself trip Jetsam, and there's
|
| 363 |
+
// no payoff if we'd have used staticGpuBudgetMB regardless.
|
| 364 |
+
const probeWorthIt = probeBestCase > staticGpuBudgetMB;
|
| 365 |
+
|
| 366 |
+
// Crash-loop guard: if a previous probe in this session crashed the
|
| 367 |
+
// tab, we never made it back to the post-probe sentinel clear, so the
|
| 368 |
+
// sentinel is still set on this load. Skip the probe until the user
|
| 369 |
+
// closes the tab (clears sessionStorage).
|
| 370 |
+
let prevProbeCrashed = false;
|
| 371 |
+
try {
|
| 372 |
+
prevProbeCrashed = sessionStorage.getItem(MOBILE_PROBE_SENTINEL_KEY) === '1';
|
| 373 |
+
} catch { /* sessionStorage may be disabled */ }
|
| 374 |
+
|
| 375 |
+
let gpuProbe = { probedMB: 0, error: null };
|
| 376 |
+
let probeSkipReason = null;
|
| 377 |
+
if (prevProbeCrashed) {
|
| 378 |
+
probeSkipReason = 'previous probe crashed tab';
|
| 379 |
+
} else if (!probeWorthIt) {
|
| 380 |
+
probeSkipReason = `probe ceiling ${probeBestCase} MB ≤ static ${staticGpuBudgetMB} MB`;
|
| 381 |
+
} else {
|
| 382 |
+
try { sessionStorage.setItem(MOBILE_PROBE_SENTINEL_KEY, '1'); } catch { /* noop */ }
|
| 383 |
+
gpuProbe = await probeGpuBudgetMB({
|
| 384 |
+
stepMB: MOBILE_PROBE_STEP_MB,
|
| 385 |
+
maxMB: probeCap,
|
| 386 |
+
timeoutMs: MOBILE_PROBE_TIMEOUT_MS,
|
| 387 |
+
yieldMs: MOBILE_PROBE_YIELD_MS,
|
| 388 |
+
});
|
| 389 |
+
try { sessionStorage.removeItem(MOBILE_PROBE_SENTINEL_KEY); } catch { /* noop */ }
|
| 390 |
+
}
|
| 391 |
|
| 392 |
const margined = gpuProbe.probedMB - MOBILE_PROBE_SAFETY_MARGIN_MB;
|
| 393 |
let gpuBudgetMB;
|
| 394 |
let source;
|
| 395 |
+
if (probeSkipReason) {
|
| 396 |
+
gpuBudgetMB = staticGpuBudgetMB;
|
| 397 |
+
source = `mobile probe skipped (${probeSkipReason}), using static ${staticGpuBudgetMB} MB for ${mobileFamily}`;
|
| 398 |
+
} else if (gpuProbe.probedMB > 0 && margined > staticGpuBudgetMB) {
|
| 399 |
gpuBudgetMB = margined;
|
| 400 |
const hitCap = gpuProbe.probedMB + MOBILE_PROBE_STEP_MB > probeCap;
|
| 401 |
const detail = hitCap
|
|
|
|
| 426 |
probedMB: 0,
|
| 427 |
gpuProbedMB: gpuProbe.probedMB,
|
| 428 |
probeError: 'skipped on mobile (heap probe can trip Jetsam)',
|
| 429 |
+
gpuProbeError: gpuProbe.error || (probeSkipReason ? `skipped: ${probeSkipReason}` : null),
|
| 430 |
isMobile: true,
|
| 431 |
mobileFamily,
|
| 432 |
source: source + adapterDetail,
|