-
Type:
Improvement
-
Resolution: Won't Fix
-
Priority:
Minor - P4
-
None
-
Affects Version/s: None
-
Component/s: Query Execution
-
None
-
Query Execution
-
QE 2026-08-03, QE 2026-08-17
-
200
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Overview
On the classic $geoNear hot path, StoredGeometry::extractGeometries() (src/mongo/db/geo/geometry_container.cpp) allocates one StoredGeometry on the heap per extracted geometry (via std::unique_ptr) and collects them into a std::vector[std::unique\_ptr<StoredGeometry|std::unique_ptr<StoredGeometry]>. Both allocations happen once per candidate document in computeGeoNearDistance(). Holding StoredGeometry by value in a small inline vector removes both allocations.
Background: headroom analysis
Flamegraph analysis of the classic 2dsphere workload (on-CPU, drift-invariant inclusive %):
* computeGeoNearDistance = 22.1% (2dsphere), 15.5% (2d)
* extractGeometries = 6.78% (2dsphere), 6.53% (2d), of which:
** alloc/free = 2.15% / 2.58% (the avoidable part: unique_ptr + set node + vector)
** parseFromStorage = 2.99% (inherent S2 geometry parsing, not avoidable)
** allocation inside the BSONElementSet (std::set) itself = only 0.28%
The std::set is mostly comparator/tree work, not allocation, so replacing it recovers only ~0.3% and requires an invasive rewrite of multikey path extraction; it is intentionally left alone. The real avoidable cost is the per-geometry unique_ptr heap allocation.
Proposed Change
* Add a defaulted move constructor and move assignment to GeometryContainer. It currently declares a copy constructor, which suppresses the implicit move constructor; without an explicit move, storing StoredGeometry by value would deep-clone the geometry via clonable_ptr on every vector growth (worse than the status quo). All members (clonable_ptr, unique_ptr, BSONElement) are movable, so = default is safe. This is a general improvement in its own right.
* Change StoredGeometry::extractGeometries to collect into absl::InlinedVector by value (new StoredGeometry::Vector type alias), removing the per-geometry unique_ptr allocation and the vector heap allocation for the common single/double-geometry case.
* Convert StoredGeometry::parseFrom from a static factory returning a heap pointer into a member bool parseFrom(...) that parses in place (emplace_back().parseFrom(), pop_back() on failure).
* Update the two callers (src/mongo/db/exec/classic/geo_near.cpp and src/mongo/db/exec/agg/internal_compute_geo_near_distance_stage.cpp) to iterate by value.
Prototype Data
Prototyped and measured locally (classic engine forced, Standalone inMemory, ARM) on Aggregation.GeoNear2dSphere / Aggregation.GeoNear2d. Because the measured effect is small and the host exhibited 15-20% performance drift across the session, the flamegraph (drift-invariant proportions) is the reliable signal, not raw ops/sec.
Flamegraph, baseline -> prototype:
* 2dsphere: computeGeoNearDistance 22.10% -> 20.98%; extractGeometries 6.78% -> 5.42%; extractGeometries alloc/free 2.15% -> 1.48%
* 2d: computeGeoNearDistance 15.49% -> 14.14%; extractGeometries 6.53% -> 5.43%; extractGeometries alloc/free 2.58% -> 1.68%
Net: approximately 1.1-1.4 percentage points of total CPU removed (~0.7-0.9pp of it allocation). Interleaved ops/sec A/B was inconclusive (round 1 +5.2%, round 2 +0.2%), i.e. at/below the noise floor on the drifting host.
Correctness: a custom harness verified an exact result signature (ids + distances) identical to baseline for both 2d and 2dsphere.
Relationship to SERVER-132107
This is a separate, much smaller optimization in the same function than SERVER-132107 (defer point-metadata Value construction, ~+20-24% on 2dsphere). This change targets the extraction allocations rather than the metadata Value. They are independent and can be reviewed/merged separately.
Scope of Work
* src/mongo/db/geo/geometry_container.h — add GeometryContainer move ctor/assignment; add StoredGeometry::Vector; make parseFrom a member.
* src/mongo/db/geo/geometry_container.cpp — rewrite parseFrom/extractGeometries to parse in place by value.
* src/mongo/db/exec/classic/geo_near.cpp, src/mongo/db/exec/agg/internal_compute_geo_near_distance_stage.cpp — iterate by value.
Acceptance Criteria
* $geoNear results and distance/point metadata are unchanged.
* No per-geometry heap allocation in extractGeometries for the common (inline-capacity) case.
* Existing $geoNear correctness tests pass.
Technical Notes
* The prototype patch is attached to this ticket.
* Since this touches the query hot path, a sys-perf patch is recommended before merge.