Summary
mmcdole/gofeed v1.3.0 → v1.4.1 roughly doubles the cost of the feed parse
path. #210 holds the parser at v1.3.0 so the rest of that dependency group
could land; this issue tracks actually taking the upgrade.
Measurement
Measured on top of main with only gofeed bumped (go get github.com/mmcdole/gofeed@v1.4.1), leaving the go directive at 1.25.9 so the
toolchain change that rode along in the group PR isn't a confounder.
BenchmarkParseRSS, -benchmem -count=6, benchstat:
ParseRSS-16 sec/op 707.7µ ± 4% → 1330.0µ ± 13% +87.94% (p=0.002 n=6)
ParseRSS-16 B/op 878.9Ki ± 0% → 1572.7Ki ± 0% +78.95% (p=0.002 n=6)
ParseRSS-16 allocs/op 8.498k ± 0% → 24.801k ± 0% +191.85% (p=0.002 n=6)
These numbers match the group PR's gate failure exactly, and pinning gofeed
back returns ParseRSS to baseline (~, p=0.310), so the parser bump accounts
for the entire regression.
The allocation count is the tell: +192% allocs/op for the same input is a
per-item or per-element allocation that used to be avoided, not a constant-factor
slowdown. sec/op tracking it at ~+88% is consistent with allocator/GC pressure
being the mechanism rather than added parsing work.
Why it matters here
Feed parsing is the service's hot path — every poll cycle, every feed. At the
default poll intervals a 2x parse cost is mostly GC pressure rather than
wall-clock risk, but it scales with feed count, and the catalog ships 179+ feeds.
What to do
Notes
scripts/bench-compare.sh caught this on the dependency PR before it merged,
which is exactly the job it was added for.
Summary
mmcdole/gofeedv1.3.0 → v1.4.1 roughly doubles the cost of the feed parsepath. #210 holds the parser at v1.3.0 so the rest of that dependency group
could land; this issue tracks actually taking the upgrade.
Measurement
Measured on top of
mainwith only gofeed bumped (go get github.com/mmcdole/gofeed@v1.4.1), leaving thegodirective at 1.25.9 so thetoolchain change that rode along in the group PR isn't a confounder.
BenchmarkParseRSS,-benchmem -count=6, benchstat:These numbers match the group PR's gate failure exactly, and pinning gofeed
back returns
ParseRSSto baseline (~, p=0.310), so the parser bump accountsfor the entire regression.
The allocation count is the tell: +192% allocs/op for the same input is a
per-item or per-element allocation that used to be avoided, not a constant-factor
slowdown.
sec/optracking it at ~+88% is consistent with allocator/GC pressurebeing the mechanism rather than added parsing work.
Why it matters here
Feed parsing is the service's hot path — every poll cycle, every feed. At the
default poll intervals a 2x parse cost is mostly GC pressure rather than
wall-clock risk, but it scales with feed count, and the catalog ships 179+ feeds.
What to do
goxppdependency also moved, and it's the XML pull-parser underneath — suspect
it first).
upstream with this benchmark attached.
dependabot.ymlignore entry sothe group PR doesn't keep re-proposing it.
go.modonce resolved.Notes
scripts/bench-compare.shcaught this on the dependency PR before it merged,which is exactly the job it was added for.