Quiet the debug-noise that was lagging the browser
You're right — the telemetry path itself was contributing to perceived
browser lag, not just the GPU work. Two specific sources removed:
render/mod.rs::rebuild_chunk:
- Per-chunk log::info!("rebuild_chunk {coord}: {ms}ms ...") fired
~289 times during world init, plus on every edit. Chrome's console
buffer accumulates these and DevTools recalcs on each new line.
Removed entirely. The bench toggles + FPS HUD already give us the
measurement signal; per-chunk timing was noise once verified.
web/main.js setupFpsHud:
- Was a 5 Hz setInterval that did `el.textContent = ...` and two
`classList.toggle` calls each tick (15 DOM writes/sec). Now:
* Polls at 1 Hz (the EMA already smooths)
* Only writes textContent when the displayed string actually
changes (skip is the common case once stabilized)
* Only writes class when the tier (green/warn/bad) crosses
a threshold
Same readout, ~15× fewer DOM writes.
web/main.js setupStatusLoop (HP bar):
- Same dedupe pattern. 10 Hz polling, but DOM writes only when
hp or alive changes from the last sample. Was firing 3 style
writes per tick unconditionally; now zero in steady state.
No functionality changes — every telemetry getter, every bench
toggle, every test-harness export still works (just verified via
the 18-check functional contract suite).
Wasm release built; tests 63/63 pass.
This commit is contained in:
parent
d622cdb330
commit
a01d5c1fa9
2 changed files with 38 additions and 25 deletions
|
|
@ -507,20 +507,12 @@ impl Renderer {
|
||||||
// immutable &World into build_chunk_mesh while still owning
|
// immutable &World into build_chunk_mesh while still owning
|
||||||
// &mut self below.
|
// &mut self below.
|
||||||
let chunk_clone = chunk.clone();
|
let chunk_clone = chunk.clone();
|
||||||
let t0 = browser_now();
|
// Mesh build no longer logs per chunk — the per-frame spam
|
||||||
|
// (~289 entries during init) was filling the browser console
|
||||||
|
// and contributing to perceived browser lag, especially with
|
||||||
|
// DevTools open. Use the FPS HUD / bench toggles for runtime
|
||||||
|
// perf measurement instead.
|
||||||
let mesh = build_chunk_mesh(world, &chunk_clone);
|
let mesh = build_chunk_mesh(world, &chunk_clone);
|
||||||
let mesh_ms = browser_now() - t0;
|
|
||||||
// Lowered threshold so the heightmap-fast path also surfaces
|
|
||||||
// in telemetry. Tune up later if it gets noisy.
|
|
||||||
if mesh_ms > 0.5 {
|
|
||||||
log::info!(
|
|
||||||
"rebuild_chunk {:?}: {:.1}ms ({} verts, {} idx)",
|
|
||||||
coord,
|
|
||||||
mesh_ms,
|
|
||||||
mesh.vertices.len(),
|
|
||||||
mesh.indices.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if mesh.indices.is_empty() {
|
if mesh.indices.is_empty() {
|
||||||
self.chunk_buffers.remove(&coord);
|
self.chunk_buffers.remove(&coord);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
45
web/main.js
45
web/main.js
|
|
@ -202,12 +202,24 @@ function setupMenu() {
|
||||||
function setupStatusLoop() {
|
function setupStatusLoop() {
|
||||||
const hpFill = document.getElementById("hp-fill");
|
const hpFill = document.getElementById("hp-fill");
|
||||||
const hpLabel = document.getElementById("hp-label");
|
const hpLabel = document.getElementById("hp-label");
|
||||||
|
let lastHp = -1;
|
||||||
|
let lastAlive = null;
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const hp = wasm.get_hp();
|
const hp = wasm.get_hp();
|
||||||
const alive = wasm.is_alive();
|
const alive = wasm.is_alive();
|
||||||
hpFill.style.width = (hp / 20 * 100) + "%";
|
// Dedupe: only touch the DOM when something actually changed.
|
||||||
hpLabel.textContent = `${hp} / 20`;
|
// Pre-change the loop ran 10× per second and fired three style
|
||||||
document.body.classList.toggle("dead", !alive);
|
// writes each time — every frame paying a recalc cost even when
|
||||||
|
// HP held steady. Worth-only-noticeable when the value changes.
|
||||||
|
if (hp !== lastHp) {
|
||||||
|
hpFill.style.width = (hp / 20 * 100) + "%";
|
||||||
|
hpLabel.textContent = `${hp} / 20`;
|
||||||
|
lastHp = hp;
|
||||||
|
}
|
||||||
|
if (alive !== lastAlive) {
|
||||||
|
document.body.classList.toggle("dead", !alive);
|
||||||
|
lastAlive = alive;
|
||||||
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -678,22 +690,31 @@ function cycleHotbar(delta) {
|
||||||
wasm.select_block(b);
|
wasm.select_block(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FPS HUD — reads the EMA-smoothed dt published by App::publish_telemetry
|
// FPS HUD — reads the EMA-smoothed dt from the game and writes it
|
||||||
// each frame. Polled every 200ms (5Hz) which is plenty for a readable
|
// once a second. The previous version polled at 5 Hz with DOM writes
|
||||||
// number without adding measurable overhead. Coloring: green ≤ 18ms,
|
// every poll, which on weak hardware contributed to perceived browser
|
||||||
// amber 18-33ms, red beyond.
|
// lag. 1 Hz is more than enough to read the number; the EMA already
|
||||||
|
// smooths anything faster anyway. Also skips DOM writes when the
|
||||||
|
// reported value hasn't changed enough to display differently.
|
||||||
function setupFpsHud() {
|
function setupFpsHud() {
|
||||||
const el = document.getElementById("fps");
|
const el = document.getElementById("fps");
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
let lastText = "";
|
||||||
|
let lastTier = "";
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const dt = wasm.get_frame_dt_ms ? wasm.get_frame_dt_ms() : 0;
|
const dt = wasm.get_frame_dt_ms ? wasm.get_frame_dt_ms() : 0;
|
||||||
if (!dt || dt <= 0) {
|
if (!dt || dt <= 0) {
|
||||||
el.textContent = "— fps";
|
if (lastText !== "— fps") { el.textContent = "— fps"; lastText = "— fps"; }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fps = 1000 / dt;
|
const fps = 1000 / dt;
|
||||||
el.textContent = `${fps.toFixed(0)} fps (${dt.toFixed(1)}ms)`;
|
const next = `${fps.toFixed(0)} fps (${dt.toFixed(1)}ms)`;
|
||||||
el.classList.toggle("warn", dt > 18 && dt <= 33);
|
if (next !== lastText) { el.textContent = next; lastText = next; }
|
||||||
el.classList.toggle("bad", dt > 33);
|
const tier = dt > 33 ? "bad" : dt > 18 ? "warn" : "";
|
||||||
}, 200);
|
if (tier !== lastTier) {
|
||||||
|
el.classList.toggle("warn", tier === "warn");
|
||||||
|
el.classList.toggle("bad", tier === "bad");
|
||||||
|
lastTier = tier;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue