-
Type:
Improvement
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Execution
-
Fully Compatible
-
QE 2026-08-31
-
200
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Scope
SBE only. This covers mongo::sbe::bson in src/mongo/db/exec/sbe/values/bson.h. It does not touch BSONElement/BSONObj, the classic execution engine, or any other BSON parsing path.
Context
While investigating BF-45431 (MatchAndGroupLookupUnwind regressed ~3% vs 8.3), profiling the shape on top_twenty_shapes_locust / perf-3-node-replSet.arm.aws.2024-05 showed roughly 7% of cycles in libc strlen, some share of it reached through SBE's BSON field-name helpers. Field-name handling in the SBE scan stage accounted for a large fraction of ScanStageBaseImpl::getNext() and sbe::bson::getField().
Problem
The three helpers that need a field name's length did it three different ways:* getField() probed the first nine bytes with unrolled byte comparisons, falling back to strlen() only for longer names.
- fieldNameAndLength() called strlen() unconditionally, despite being on the same per-element path -- the multi-field scan in placeFieldsFromRecordInAccessors() calls it for every field of every document.
- getValue() also called strlen() unconditionally.
Change
Extract the probe as fieldNameLength() and use it from all three. Field names of eight bytes or fewer, which dominate, no longer pay for a call; longer names behave exactly as before.
Measurements
sbe_get_field_bm was used to evaluate alternatives. A SWAR (SIMD Within A Register) word-at-a-time scan replacing the unrolled probe entirely was tried and rejected: it regressed short names by up to 116%, because the measured benefit is the removed call (a constant ~1.4ns per element, independent of name length) rather than faster scanning. Retaining the unrolled probe and using SWAR only beyond eight bytes measured -5% geomean, but was dropped in favour of the simpler shared-probe change.
Validation
PMS comparison 6a7cadcda97f1cbbd681b7bb -- 5 patches vs 5 at the merge base, perf-required.
Follow-ups (not in scope here)
- No unit coverage exists for fieldNameLength(); the edges worth testing are empty names, lengths 7/8/9, and names ending within eight bytes of the document end.
- SWAR for names of nine or more bytes, if the microbenchmark case is judged worth the complexity.
- The remaining cost in that loop is the walk's dependency chain (type byte -> kAdvanceTable -> next element), which a field-shape hint would attack.
- is duplicated by
-
SERVER-133054 Consolidate how we measure string length in SBE
-
- Closed
-
- related to
-
SERVER-133054 Consolidate how we measure string length in SBE
-
- Closed
-