-
Type:
Task
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Performance
-
None
-
Query Integration
-
Fully Compatible
-
v9.0
-
200
-
None
-
None
-
None
-
None
-
None
-
None
-
None
What
`$round`/`$trunc` on a `double` unconditionally round-trips through `Decimal128` (`double -> Decimal128 -> quantize -> double`) in `evaluateRoundOrTrunc`, regardless of precision.
Add a native fast path: when the precision is `0` and the value is a finite double, use native floating-point rounding (`std::nearbyint` for `$round`, `std::trunc` for `$trunc`) and skip Decimal128.
- `$round` uses `nearbyint` (ties-to-even under the default `FE_TONEAREST`, matching `kRoundTiesToEven`); `std::round` would be wrong for ties (half-away-from-zero).
- Non-integer precision, `Decimal128`, `int`/`long`, and non-finite inputs are unchanged (still go through the Decimal128 path). For integer precision the result is numerically identical to the Decimal128 quantize.
Why
Profiling `tsbs-expression-query` (`single_groupby_1_1_1_round`) showed `evaluateRoundOrTrunc` was ~11% of the non-idle CPU, ~80% of which is Decimal128 machinery
(`Decimal128::quantize`, `{}bid128{_}*`, double<->Decimal128 conversions) for what is a precision-0 round of a double.