perf: choose the codec when the decoder is built - #37
Merged
Conversation
decode/2 matched a scalar decoder and then called decode_named/4, which walked the names that need a codec of their own before falling through to the scalar one. The name is fixed by the RowDescription, so that walk answered the same question once per value. The decoder now carries which codec to call, so decode/2 is one clause and one call. decode_named/4 stays for decode/4, which has no decoder to carry it. 112,898 to 103,685 reductions per five thousand row query.
🟢 Code Coverage — 90.2%1624 of 1801 lines covered. ✅ ELP LintNo diagnostics. |
This was referenced Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third of the items the profile turned up:
minato_codec:decode/2anddecode_named/4were each called once per column, 16% of the profile combined, for what is one logical operation.decode/2matched a scalar decoder and then calleddecode_named/4, which tested fornumeric, then for the four datetime names, before falling through to the scalar codec. Those names are fixed by theRowDescription, so the walk was answering the same question once per value.The decoder now carries which codec to call.
decode/2is one clause and one static call.decode_named/4stays, becausedecode/4has no decoder to carry the answer.Cumulative over #33, #34, #35 and this: 172,841 to 103,685, 40% less work per query.
The opaque
decoder()gained tighter types on the way:{numeric, format(), opts()}and{datetime, date | time | timestamp | timestamptz, format(), opts()}. eqwalizer rejected the first attempt, which passed the whole name union to codecs that accept one name or four - correlating the tag with the name inresolved/3fixed it, and the types now say what each codec actually takes.Checklist green: fmt, xref, dialyzer, eqwalize-all, elp lint, ex_doc, 1398 eunit, 137 ct.