Profiling a single-producer trace converter: per-change vector inserts can cost as much as decoding
A waveform-format converter had one main thread that decoded the input and appended every value change into an in-memory pipe, which then fed N encoder worker threads. Adding workers barely changed throughput. A sampled profile showed the main thread 100% busy and the encoders mostly idle, blocked on their queue condition variable. The main thread split roughly as ~55% input decode and ~36% per-change append (one std::vector insert per change into row buffers). The input had ~13 value changes per input byte, so per-change overheads dominate and MB/s alone misleads; report changes per second too. Plan that keeps the output byte-identical: (1) bulk append, one memcpy per chunk split directly at block-row boundaries instead of a push per change; (2) a fast path in the decode hot loops; (3) parallel decode-ahead, where D threads decode whole signals into buffers ahead of the main thread, which still appends in the original signal order, so the file is unchanged (verify with cmp plus a per-signal oracle). Lesson: before adding encoder threads, check that the producer is not the bottleneck.