Skip to content

Slow scan: poetry hosted 4.5x median ms/pkg (per-patch poetry.lock re-parse) #760

Description

[agent] Bench: poetry has been flagged slow in 3 consecutive benchmark runs (2026-10-02, 10-03, 10-04). Its hosted scan costs about 4.5x the median ms per package across all package managers.

run poetry/hosted median ms/pkg x median ms/pkg poetry/rescan median
2026-10-02 187.6 ms 0.469 3.7x 170.3 ms
2026-10-03 221.4 ms 0.554 4.3x 224.4 ms
2026-10-04 201.6 ms 0.504 4.5x 175.1 ms

Fixture: 400 packages, 12 patched, poetry.lock 2.1, in-project .venv. For comparison, pip/hosted (1000 packages, 25 patched) takes 81.8 ms (0.082 ms/pkg) on the same runner.

Hot spot (callgrind, poetry/hosted, 2026-10-04)

  • patch::redirect::poetry::rewrite_poetry → utils::poetry_lock::rewrite_poetry_lock_in: 77% of all instructions.
    • toml_edit::Document::parse: 45.5%
    • DocumentMut Display (re-serialize): 18.2%
  • rewrite_poetry loops over the patched deps and calls rewrite_poetry_lock_in once per dep. PoetryLockParse reuses a parse only while doc.raw() == text. Each rewrite mutates the doc and re-serializes it to new text, so the next dep misses the cache and re-parses the whole lock. Cost is O(patches × lock size): 12 full parses and 12 full serializations of poetry.lock here.
  • Possible fix: plan every dep against one parsed DocumentMut, apply all mutations, then serialize once. Per-dep edits() fragments could come from the original text plus the final document.
  • Secondary: vex::discover::pypi_locks::extract (10.4%) parses the lock again for VEX.

Runner

4 vCPU, Intel(R) Xeon(R) Processor @ 2.10GHz (cloud sandbox), main 045d7ec7. Absolute timings vary from runner to runner; the ratio to the cross-PM median is the signal.

Repro

CARGO_PROFILE_PERF_INHERITS=release CARGO_PROFILE_PERF_LTO=thin CARGO_PROFILE_PERF_STRIP=none \
  cargo build --locked --profile perf -p socket-patch-cli -p socket-patch-bench
target/perf/socket-patch-bench run --bin target/perf/socket-patch -f '^poetry/' -v
# profile: serve the fixture, then prefix the printed command's binary with
#   valgrind --tool=callgrind
target/perf/socket-patch-bench serve poetry/hosted --bin target/perf/socket-patch

Tracked in the ledger of #575 (standing slow-systems list). This is a standing slowness report, not a regression: the cost has been flat since the suite started.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions