perf: compose 30% faster — move semantics, BFS offsets, zero-alloc hex formatting

- compose.cpp: emitLine takes LineMeta&& (move, not copy) at all 22 call sites
- compose.cpp: reserve meta/text buffers, BFS offset computation O(N) vs O(N*D)
- compose.cpp: pre-compute typeNameLens[], merge global width loops
- format.cpp: bytesToHex uses stack buffer + lookup table (zero heap allocs)
- format.cpp: hexVal single QString::asprintf instead of 2-string concat
- editor.cpp: guard hover updates during applyDocument (stale index safety)
- core.h: assertion on makeArrayElemSelId negative index
- format.cpp: assertion on extractBits overflow
- main.cpp: tree lines enabled by default
- bench_large_class: add 2000-field benchComposeLarge test

Benchmark: 500 fields 0.70→0.51ms (27%), 2000 fields 2.28→1.57ms (31%)
This commit is contained in:
IChooseYou
2026-03-08 07:28:26 -06:00
committed by IChooseYou
parent f0fc85f60f
commit 596f410b96
8 changed files with 150 additions and 63 deletions

View File

@@ -65,6 +65,7 @@ private:
private slots:
void initTestCase();
void benchCompose();
void benchComposeLarge();
void benchApplyDocument();
void benchHoverHighlight();
void benchSelectionOverlay();
@@ -112,6 +113,36 @@ void BenchLargeClass::benchCompose()
QVERIFY(elapsed > 0);
}
void BenchLargeClass::benchComposeLarge()
{
// Build a 2000-field tree to stress-test compose at scale
NodeTree bigTree = buildLargeTree(2000);
QByteArray buf(0x40000, '\0');
for (int i = 0; i < buf.size(); ++i) buf[i] = (char)(i & 0xFF);
BufferProvider bigProv(buf, QStringLiteral("bench_large"));
// Warmup
{ ComposeResult w = rcx::compose(bigTree, bigProv); Q_UNUSED(w); }
const int ITERS = 50;
QElapsedTimer timer;
timer.start();
for (int i = 0; i < ITERS; ++i) {
ComposeResult r = rcx::compose(bigTree, bigProv);
Q_UNUSED(r);
}
qint64 elapsed = timer.elapsed();
qDebug() << "";
qDebug() << "=== Compose Benchmark (2000 fields) ===";
qDebug() << " Tree:" << bigTree.nodes.size() << "nodes";
qDebug() << " Iterations:" << ITERS;
qDebug() << " Total:" << elapsed << "ms";
qDebug() << " Per-compose:" << (double)elapsed / ITERS << "ms";
QVERIFY(elapsed > 0);
}
void BenchLargeClass::benchApplyDocument()
{
RcxEditor editor;