ꘇ dat.monitor
Is it your graph or your browser that's slow?
- browser fps
- metrics
- json
Once you're running live visuals in a browser tab, "it feels laggy" stops being useful information. dat.monitor is the pack's answer: it samples the browser's animation-frame cadence over a rolling five-second window and separately counts how many frames each live texture source is actually delivering, then exposes the numbers as a FLOAT, a named CHOP block, and JSON. It's the difference between guessing and knowing whether the drop is in your shader chain or in the tab's compositor.
ꘇ Genereti (languel/genereti, Liuboto, MIT, super-alpha) is a realtime creative-coding pack for ComfyUI - TOP/CHOP/DAT operators, Web Audio, perception, a performance timeline. Monitoring shows up in a pack like this precisely because the live path deliberately happens outside Comfy's queue, where the normal progress bar tells you nothing.
What it reads and what it emits
The inputs are almost nothing: one optional report STRING, default {}. In Live, the browser fills the node's own display from its measurements; the report is the captured snapshot. On Queue, the node preserves a captured monitor report rather than inventing one - the docs are explicit that it "does not turn backend execution time into FPS." So this is a browser instrument, not a profiler for your sampler.
Outputs:
browser fps(FLOAT) - the headline numbermetrics(GENERETI_CHOP) - a one-sample-per-value channel block at 1 Hz containingfps,meanMs,p95Ms,worstMs,slowFrames,longTasksjson(STRING) - the raw report, forꘇ dat.inspector a text output
The metrics are the interesting ones. meanMs is the average frame interval; p95Ms and worstMs are the tail, which is where stutter actually lives - an average of 60 fps with a 200 ms worst frame is a visibly juddering patch. slowFrames counts frames over 50 ms. longTasks is populated only where the browser exposes Long Tasks. The dock also reports transport-tick and UI-commit costs, which matters more than you'd guess: in this pack the timeline reconciles at 5 Hz and control updates run at 25 Hz, so a slow UI can eat your frame budget even when your GPU work is trivial.
Reading it without fooling yourself
The single most important caveat is stated by the author in bold terms: browser FPS is neither measured GPU execution time nor your audio/Comfy Queue rate. It's the browser's animation-frame cadence. Source deliveries can keep flowing while a local preview is frozen; measurements reset when the page's visibility changes; other tabs, background throttling and the compositor all move these numbers. So treat this as "is the live display smooth," not "how fast is my model."
In practice, use it for comparisons, not absolutes. Turn one shader chain on, watch p95Ms; turn it off, watch it again. That delta is real information. The absolute 58 fps next to someone else's 60 on different hardware is not.
Install
Manager → search "Genereti" → install ꘇ Genereti → restart ComfyUI → refresh the page. Manual:
git clone https://github.com/languel/genereti.git custom_nodes/genereti
./.venv/bin/python -m pip install -r custom_nodes/genereti/requirements.txt
Pinned requirement: comfyui-frontend-package>=1.53.6. ComfyUI 0.38.2+, Python 3.11+, and a browser with WebGPU for the live paths this node is measuring. The bundled ꘇ-Performance-Timeline example includes a dat.monitor already wired up - that's the fastest way to see it working.
Gotchas
Drive it from a live path or it tells you nothing. If nothing is producing live frames, you're measuring an idle page. The node's usefulness is proportional to how much live traffic is flowing through the TOPs.
It updates its own display about once a second, and history is bounded. Don't expect a per-frame log. The snowflake control holds the display, the reset clears the window, and download exports JSON.
Non-finite values are rejected. The node validates its report and raises if the metrics aren't finite. If you're hand-crafting a report for testing, make sure every field is a real number - a NaN or a blank string will error rather than show zero.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| reportopt | STRING | {} | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| browser fps | FLOAT | — |
| metrics | GENERETI_CHOP | — |
| json | STRING | — |