Skip to content

Decode text dates ~4x faster in C, with 1 allocation instead of 8 - #758

Merged
larskanis merged 1 commit into
ged:masterfrom
czj:perf/text-date-decoder-in-c
Oct 23, 2026
Merged

larskanis merged 1 commit into
ged:masterfrom
czj:perf/text-date-decoder-in-c

Conversation

@czj

@czj czj commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

PG::TextDecoder::Date is still written in Ruby: for each value, pg builds the input String for the Ruby decoder, then the regexp match allocates a MatchData and three capture Strings before Date.new. That's 8 objects per date, where the neighbouring TextDecoder::Timestamp and BinaryDecoder::Date are already in C.

This implements it in C, on the same model as init_inet and init_numeric: lib/pg/text_decoder/date.rb now only calls init_date. Behaviour is unchanged: only YYYY-MM-DD becomes a Date (still Date::GREGORIAN), everything else (infinity, BC dates, years beyond 9999, other DateStyles) is returned as a String, and an invalid date still raises Date::Error.

Decoding 1,000 dates through Result#values goes from 8 objects to 1 per date and gets ~4x faster (2.5–3.5 ms → 0.55–0.9 ms). In our Rails app, the homepage allocates 2,690 fewer objects per request (−2.4%).

The 5 new specs also pass on the Ruby implementation, which is how I checked the two agree. Full suite: 1,160 examples, 0 failures.


🤖 Generated with Claude Code, but prompted, read, and verified by @czj, a caring human :)

The Ruby implementation allocates the input String, a MatchData and
three capture Strings per value, before the Date itself. Parsing the
ISO format in C, like TextDecoder::Timestamp does, leaves only the Date:
8 -> 1 object per decoded date and ~4x faster on a 1000 row result.

Behaviour is unchanged: anything else than YYYY-MM-DD (infinity, BC
dates, years beyond 9999, other DateStyles) is still returned as String.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@czj czj changed the title Implement PG::TextDecoder::Date in C Decode text dates ~4x faster in C, with 1 allocation instead of 8 Oct 23, 2026
@larskanis

Copy link
Copy Markdown
Collaborator

I hoped someone will open a pull request for this. I'm happy it worked! Looks good.

@larskanis
larskanis merged commit 2daa7f1 into ged:master Oct 23, 2026
35 checks passed
@czj
czj deleted the perf/text-date-decoder-in-c branch October 24, 2026 18:04
@czj

czj commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @larskanis,

Glad you liked it! Thanks for the quick review and the merge. I'm happy to contribute.

If other spots in pg could use the same treatment, I'm up for taking a look. And if you need a hand with anything else, please don't hesitate to ask. I'd be glad to help. :)

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