Skip to content

Decode numeric to Decimal128 directly, without text round-trip#34

Merged
darthunix merged 2 commits into
darthunix:mainfrom
qsliu2017:numeric-direct-decode
Jun 14, 2026
Merged

Decode numeric to Decimal128 directly, without text round-trip#34
darthunix merged 2 commits into
darthunix:mainfrom
qsliu2017:numeric-direct-decode

Conversation

@qsliu2017

Copy link
Copy Markdown
Contributor

First of all, thanks for creating this awesome project!

Profiling pg_fusion on TPC-H Q1, slot_encoder::datum::read_numeric_decimal128_with_scale was the top hotspot. It converted each PG numeric by formatting it to a string and then parsing back into an i128.

This PR replaces that with a direct decode of the numeric varlena, ported from Postgres' numeric.c.

With this PR, TPC-H Q1 speed up ~2.3x (from ~110s to ~48s, single-threaded) in my laptop.

@darthunix darthunix self-requested a review June 12, 2026 10:57
@darthunix

Copy link
Copy Markdown
Owner

@qsliu2017 thank you so much for the PR! It’s really great that you took a look at the project, benchmarked it, and
added a solid improvement around decimal reconversion. I really appreciate it.

The change looks good to me. Could you please add yourself to AUTHORS and fix the lint failures? After
that, I’ll be happy to merge it.

qsliu2017 and others added 2 commits June 13, 2026 23:48
Replace the numeric_out text round-trip in slot_encoder's
read_numeric_decimal128_with_scale with a direct decode of the
PostgreSQL numeric varlena: accumulate the base-10000 NumericDigit
array into an i128 at the target scale, ported from PG numeric.c
internals.

The decode lives in a new PostgreSQL-runtime-free pg_type::numeric
module (pure, safe `numeric_to_decimal128(&[u8], scale, precision)`
with its own NumericDecodeError); slot_encoder just detoasts, slices,
calls it, and maps the error. Behavior is unchanged -- same NaN/Inf
and out-of-range/precision handling -- and TPC-H Q1 results are
identical while the conversion step gets much faster.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@qsliu2017 qsliu2017 force-pushed the numeric-direct-decode branch from 0901286 to 5c9ea93 Compare June 13, 2026 16:16
@qsliu2017

Copy link
Copy Markdown
Contributor Author

The change looks good to me. Could you please add yourself to AUTHORS and fix the lint failures? After that, I’ll be happy to merge it.

Done.

@darthunix darthunix merged commit 206a9c6 into darthunix:main Jun 14, 2026
1 check passed
@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.35294% with 24 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pg/slot_encoder/src/datum.rs 0.00% 13 Missing ⚠️
pg/type/src/numeric.rs 91.05% 11 Missing ⚠️
Files with missing lines Coverage Δ
pg/type/src/lib.rs 75.26% <ø> (ø)
pg/type/src/numeric.rs 91.05% <91.05%> (ø)
pg/slot_encoder/src/datum.rs 53.62% <0.00%> (+16.74%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@darthunix

Copy link
Copy Markdown
Owner

@qsliu2017 thanks a lot for your contribution!

@qsliu2017 qsliu2017 deleted the numeric-direct-decode branch June 14, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants