Skip to content

perf(schema): optimize convertType with fast paths for compatible types#931

Merged
wolveix merged 3 commits into
danielgtaylor:mainfrom
baagod:main
Jan 18, 2026
Merged

perf(schema): optimize convertType with fast paths for compatible types#931
wolveix merged 3 commits into
danielgtaylor:mainfrom
baagod:main

Conversation

@baagod

@baagod baagod commented Dec 25, 2025

Copy link
Copy Markdown
Contributor

Implement fast paths in convertType to avoid expensive slice traversal when types are identical or have compatible underlying types (e.g. json.RawMessage to []byte).

baagod and others added 2 commits December 25, 2025 23:14
Implement fast paths in convertType to avoid expensive slice traversal
when types are identical or have compatible underlying types (e.g.
json.RawMessage to []byte).
@wolveix wolveix self-assigned this Jan 18, 2026
@codecov

codecov Bot commented Jan 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.58%. Comparing base (88c6cda) to head (62bdeaa).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
schema.go 87.50% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #931      +/-   ##
==========================================
- Coverage   92.62%   92.58%   -0.04%     
==========================================
  Files          23       23              
  Lines        4499     4503       +4     
==========================================
+ Hits         4167     4169       +2     
- Misses        274      275       +1     
- Partials       58       59       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

@wolveix

wolveix commented Jan 18, 2026

Copy link
Copy Markdown
Collaborator

Thanks so much for this optimization! I spent some time putting tests and benchmarks together (with Claude's help) to compare this versus the original implementation. If you'd like to run the benchmarks yourself, extract this zip and run ./run.sh.
bench.zip


Unfortunately I noticed that your optimization caused a +32.36% increase for same type vars, but that was easy to remedy :)

Here were my results with your original implementation:

goos: darwin
goarch: arm64
pkg: tmp/bench-pr
cpu: Apple M3 Pro
                                 │  v1_norm.txt  │             v2_norm.txt             │
                                 │    sec/op     │   sec/op     vs base                │
ConvertType_Nil-12                   1.902n ± 4%   1.399n ± 3%  -26.44% (p=0.000 n=10)
ConvertType_SameType-12              3.228n ± 4%   4.272n ± 0%  +32.36% (p=0.000 n=10)
ConvertType_IntToInt64-12            24.29n ± 1%   19.43n ± 1%  -20.01% (p=0.000 n=10)
ConvertType_IntToPtr-12              52.59n ± 3%   57.52n ± 1%   +9.35% (p=0.000 n=10)
ConvertType_RawMessageToBytes-12   1635.00n ± 1%   94.26n ± 1%  -94.23% (p=0.000 n=10)
ConvertType_SmallSlice-12            582.2n ± 1%   588.7n ± 0%   +1.10% (p=0.000 n=10)
ConvertType_LargeSlice-12            51.30µ ± 1%   50.57µ ± 0%   -1.43% (p=0.000 n=10)
geomean                              121.2n        78.73n       -35.02%

                                 │  v1_norm.txt   │              v2_norm.txt               │
                                 │      B/op      │     B/op      vs base                  │
ConvertType_Nil-12                   0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_SameType-12              0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToInt64-12            8.000 ± 0%       8.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToPtr-12              16.00 ± 0%       16.00 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_RawMessageToBytes-12    855.00 ± 0%       24.00 ± 0%  -97.19% (p=0.000 n=10)
ConvertType_SmallSlice-12            448.0 ± 0%       448.0 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_LargeSlice-12          39.30Ki ± 0%     39.30Ki ± 0%        ~ (p=1.000 n=10) ¹
geomean                                         ²                 -39.98%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                 │  v1_norm.txt  │              v2_norm.txt              │
                                 │   allocs/op   │  allocs/op   vs base                  │
ConvertType_Nil-12                  0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_SameType-12             0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToInt64-12           1.000 ± 0%      1.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToPtr-12             2.000 ± 0%      2.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_RawMessageToBytes-12   65.000 ± 0%      1.000 ± 0%  -98.46% (p=0.000 n=10)
ConvertType_SmallSlice-12           23.00 ± 0%      23.00 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_LargeSlice-12          2.003k ± 0%     2.003k ± 0%        ~ (p=1.000 n=10) ¹
geomean                                        ²                -44.92%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

And here's the slight improvement with my further optimization:

goos: darwin
goarch: arm64
pkg: tmp/bench-pr
cpu: Apple M3 Pro
                                 │  v1_norm.txt  │             v2_norm.txt             │
                                 │    sec/op     │   sec/op     vs base                │
ConvertType_Nil-12                   1.866n ± 2%   1.412n ± 3%  -24.30% (p=0.000 n=10)
ConvertType_SameType-12              3.213n ± 2%   2.667n ± 1%  -17.00% (p=0.000 n=10)
ConvertType_IntToInt64-12            24.40n ± 2%   19.06n ± 1%  -21.89% (p=0.000 n=10)
ConvertType_IntToPtr-12              51.65n ± 0%   56.73n ± 2%   +9.84% (p=0.000 n=10)
ConvertType_RawMessageToBytes-12   1573.00n ± 0%   92.69n ± 1%  -94.11% (p=0.000 n=10)
ConvertType_SmallSlice-12            576.2n ± 1%   573.4n ± 1%        ~ (p=0.128 n=10)
ConvertType_LargeSlice-12            51.09µ ± 0%   51.11µ ± 3%        ~ (p=0.781 n=10)
geomean                              119.6n        73.01n       -38.95%

                                 │  v1_norm.txt   │              v2_norm.txt               │
                                 │      B/op      │     B/op      vs base                  │
ConvertType_Nil-12                   0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_SameType-12              0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToInt64-12            8.000 ± 0%       8.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToPtr-12              16.00 ± 0%       16.00 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_RawMessageToBytes-12    855.00 ± 0%       24.00 ± 0%  -97.19% (p=0.000 n=10)
ConvertType_SmallSlice-12            448.0 ± 0%       448.0 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_LargeSlice-12          39.30Ki ± 0%     39.30Ki ± 0%        ~ (p=1.000 n=10) ¹
geomean                                         ²                 -39.98%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                 │  v1_norm.txt  │              v2_norm.txt              │
                                 │   allocs/op   │  allocs/op   vs base                  │
ConvertType_Nil-12                  0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_SameType-12             0.000 ± 0%      0.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToInt64-12           1.000 ± 0%      1.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_IntToPtr-12             2.000 ± 0%      2.000 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_RawMessageToBytes-12   65.000 ± 0%      1.000 ± 0%  -98.46% (p=0.000 n=10)
ConvertType_SmallSlice-12           23.00 ± 0%      23.00 ± 0%        ~ (p=1.000 n=10) ¹
ConvertType_LargeSlice-12          2.003k ± 0%     2.003k ± 0%        ~ (p=1.000 n=10) ¹
geomean                                        ²                -44.92%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

Great work! Thanks so much!

@wolveix
wolveix merged commit b4a4ec8 into danielgtaylor:main Jan 18, 2026
2 of 4 checks passed
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