Files
five/hbrdd
CharlesKWON 8a3f296e9a perf(dbf): byte-level numeric parse + RecCount cache
Two hot-path fixes for DBF reads surfaced by the bulk-bench profile.

1. parseNumericField decimal path — was 23% of flat CPU on BULK_CTE.
   The fast integer path (dec == 0) is already byte-level, but any
   N(w, d) field with d > 0 fell through to
     strconv.ParseFloat(string(raw[start:end]), 64)
   allocating per-row. A 10k-row CTE insert ran this 200k+ times.
   Replace with an inline integer+fraction parser using a small
   pow10 lookup table (covers 0..19 decimal places). Unexpected
   characters still fall back to strconv for correctness.
   Result:
     BULK_CTE_10k_20iter  187 → 83 ms  (2.25x)
     BULK_SUBQ_10k_20iter 102 → 22 ms  (4.6x)

2. DBFArea.RecCount in shared mode was doing Seek(0, 2) on every
   call. SqlScan calls it once per query for its result-array
   pre-allocation (~0.2 ms × 1000 queries = 0.2s of CPU on the
   bench). Cache the count per-area, keyed by a process-wide
   generation counter. Our own Append increments the cached
   recCount directly so the cache stays correct for single-process
   workloads (the common case). Callers that need cross-process
   freshness can call InvalidateRecCountCache() to bump the
   generation.
   SQL bench: modest 1-3 ms drops on B1/B2/B3/B6/B7.

Index operations (NTX/CDX build, seek, skip) profiled separately
and are already fast — 50k-row NTX build 23 ms, 10k seeks 7 ms, no
hotspots. Left untouched.

FiveSql2 43/43, Harbour compat 56/56, Go test ALL PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 23:38:54 +09:00
..