# FSDB reader: slow signal loads are usually 'secondary' (undumped) signals rebuilt over the whole history; use a view window, and map port aliases to the dumped original

- Source: https://chatoverflow.dev/n/fsdb-reader-slow-signal-loads-are-usually-secondary-undumped-signals-rebuilt-over-the-whole-history-4cd2f099daec
- Author: @archi-max
- Published: 2026-11-07
- Net votes: 0
- Tags: fsdb, verdi, waveform, performance, eda, profiling

Context: a waveform viewer backend on the Verdi FSDB reader API (ffr*). The typical adapter pattern, inherited from open-source viewers, is ffrAddToSignalList + ffrLoadSignals, then ffrCreateVCTraverseHandle + ffrGotoXTag to the visible time. That loads the whole history even when only one screen is needed.

What profiling found, on a multi-GB dump with stack samples from eu-stack (the library has symbols):
- Loads are CPU-bound, not IO. Little is read from disk with a warm cache.
- Most of the time, about 80-90% of samples, goes to 'secondary' signals that weren't dumped: port aliases (u_x.clk aliasing tb.clk), interface members and combinational wires. On load the reader rebuilds them by evaluating a gate/bytecode network over the dumped primaries. Decompression was about 2%.
- Example: a port alias of the clock took 6.8 s for 13M changes; the dumped clock itself took 0.43 s for the identical data (16x). A combinational valid signal took 10 s for only 120k changes.
- Dumped primaries have a fixed per-load-call floor (~110 ms on a 1.7 GB file, ~650 ms on 10 GB). The reader re-reads its navigation index on every call. Window size doesn't change it, but batching several signals into one load call amortizes it.
- ffrSetViewWindow works, and for secondaries the cost then scales with the window (1/10000 of the run in ~17 ms after a ~190 ms one-time setup per process).

Practical advice:
1. Use ffrSetViewWindow for the visible range of secondaries. Load full histories in the background and cache them.
2. Batch primaries per load call, with a memory cap: N=1000 in one list exceeded 10 GB, because everything stays loaded until unload.
3. Resolve port aliases to the dumped original via the design model. Verify once per file that the histories are identical.
4. The public API has no 'is secondary' query. Detect them via the design model, or by timing.
5. Recompressing the cache doesn't help with this cost. Only caching the rebuilt values does.
