Skip to content

perf: reuse Conda history while parsing environments (Fixes #475) - #493

Merged
Karthik Nadig (karthiknadig) merged 3 commits into
mainfrom
perf/issue-475
Aug 5, 2026
Merged

perf: reuse Conda history while parsing environments (Fixes #475)#493
Karthik Nadig (karthiknadig) merged 3 commits into
mainfrom
perf/issue-475

Conversation

@karthiknadig

Copy link
Copy Markdown
Member

Summary

  • read conda-meta/history once per environment parse
  • reuse the snapshot for manager discovery, Python package metadata, and environment naming
  • preserve package JSON fallback when history is absent or incomplete
  • add regression coverage that verifies one history-reader invocation

Validation

  • cargo test -p pet-conda
  • .\scripts\rust-precommit.ps1

Fixes #475

Read conda-meta/history once per environment and share the snapshot across manager, package, and name parsing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Test Coverage Report (Linux)

Metric Value
Current Coverage 80.5%
Base Branch Coverage 80.4%
Delta .1% ✅

Coverage increased! Great work!

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Performance Report (Linux) ✅

Metric PR (P50) PR (P95) Baseline (P50) Delta Change
Server Startup 1ms 1ms 0ms 1ms N/A%
Full Refresh 48ms 254ms 50ms -2ms 0%

Results based on 10 iterations. P50 = median, P95 = 95th percentile.


Legend
  • 🚀 Significant speedup (>100ms faster)
  • ✅ Faster than baseline
  • ➖ No significant change
  • 🔺 Slower than baseline (>100ms)
  • ⚠️ Significant slowdown (>500ms)

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Performance Report (macOS)

Metric PR (P50) PR (P95) Baseline (P50) Delta
Server Startup 103ms 10236ms 119ms -16ms
Full Refresh 178ms 30293ms 282ms -104ms

Results based on 10 iterations. P50 = median, P95 = 95th percentile.


Legend
  • 🚀 Significant speedup (>100ms faster)
  • ✅ Faster than baseline
  • ➖ No significant change
  • 🔺 Slower than baseline (>100ms)
  • ⚠️ Significant slowdown (>500ms)

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Test Coverage Report (Windows)

Metric Value
Current Coverage 77.31%
Base Branch Coverage 77.19%
Delta 0.12% ✅

Coverage increased! Great work!

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Performance Report (Windows) ➖

Metric PR (P50) PR (P95) Baseline (P50) Delta Change
Server Startup 8ms 10ms 9ms -1ms -11.1%
Full Refresh 137ms 1487ms 137ms 0ms 0%

Results based on 10 iterations. P50 = median, P95 = 95th percentile.


Legend
  • 🚀 Significant speedup (>100ms faster)
  • ✅ Faster than baseline
  • ➖ No significant change
  • 🔺 Slower than baseline (>100ms)
  • ⚠️ Significant slowdown (>500ms)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces redundant synchronous I/O during Conda environment discovery by reading conda-meta/history once per environment parse and reusing that snapshot for multiple parsing steps. This aligns with PET’s performance goals by minimizing filesystem reads in hot discovery paths.

Changes:

  • Read conda-meta/history once per CondaEnvironment parse and thread the contents through conda-dir detection, env naming, and Python package metadata extraction.
  • Refactor CondaPackageInfo to accept optional pre-read history content and optimize history scanning (use reverse search instead of collecting matches).
  • Add a regression test to ensure the environment-info path only invokes the history reader once.
Show a summary per file
File Description
crates/pet-conda/src/package.rs Adds history-reuse entry points for package parsing and avoids extra allocations when selecting the most recent matching history entry.
crates/pet-conda/src/environments.rs Reads history once per env parse, reuses the creation line for conda-dir and name derivation, and adds a “reads history once” regression test.

Review details

Comments suppressed due to low confidence (2)

crates/pet-conda/src/environments.rs:410

  • These tests now pass the entire history file contents into get_conda_env_name's creation_line parameter. That weakens the assertion because get_conda_env_name_from_creation_line is intended to receive only the filtered # cmd: ... create ... line; passing full history could accidentally match -n <name> in unrelated commands. Extract the creation line via get_conda_creation_line(&history) and pass as_deref() instead.
        let history = std::fs::read_to_string(&history_file).unwrap();
        let name = get_conda_env_name(&env_path, &conda_dir, Some(&history));

crates/pet-conda/src/environments.rs:490

  • These tests now pass the entire history file contents into get_conda_env_name's creation_line parameter. That weakens the assertion because get_conda_env_name_from_creation_line is intended to receive only the filtered # cmd: ... create ... line; passing full history could accidentally match -n <name> in unrelated commands. Extract the creation line via get_conda_creation_line(&history) and pass as_deref() instead.
        let history = std::fs::read_to_string(&history_file).unwrap();
        let name = get_conda_env_name(&env_path, &conda_dir, Some(&history));
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Low

Comment thread crates/pet-conda/src/environments.rs Outdated
Comment thread crates/pet-conda/src/environments.rs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (2)

crates/pet-conda/src/environments.rs:55

  • This function reads conda-meta/history once for environment parsing, but the base environment can still cause a second read of the same file when manager discovery runs (e.g., CondaManager::from(prefix) calls get_conda_installation_used_to_create_conda_env(path), which reads history again when path is the conda install/base env). This means the PR’s stated “reuse … for manager discovery” / “one read per env per find()” goal isn’t fully met for the base env case.

Consider either (a) avoiding history reads in CondaManager::from when path is already a conda install (is_conda_install(path) fast-path), or (b) plumbing the already-read history/creation line into manager detection (or a per-refresh history cache) so manager lookup can reuse it.

pub fn get_conda_environment_info(
    env_path: &Path,
    manager: &Option<CondaManager>,
) -> Option<CondaEnvironment> {
    get_conda_environment_info_with_history_reader(env_path, manager, |env_path| {
        std::fs::read_to_string(env_path.join("conda-meta").join("history")).ok()
    })

crates/pet-conda/src/environments.rs:169

  • get_conda_creation_line lowercases each candidate line using full Unicode case-folding (to_lowercase()), which is relatively expensive for a hot-path parser. Since the history format is ASCII, to_ascii_lowercase() is sufficient and avoids the heavier Unicode mapping.
    let line = history.lines().map(str::trim).find(|line| {
        let line = line.to_lowercase();
        line.starts_with("# cmd:") && line.contains(" create -")
    })?;
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Low

Use ASCII-insensitive byte-stable matching and checked slicing for history command extraction.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Low

@karthiknadig
Karthik Nadig (karthiknadig) merged commit c56e2a3 into main Aug 5, 2026
38 checks passed
@karthiknadig
Karthik Nadig (karthiknadig) deleted the perf/issue-475 branch August 5, 2026 21:27
Karthik Nadig (karthiknadig) added a commit that referenced this pull request Aug 5, 2026
## Summary

- add a PET-wide Rust coding skill alongside locator-specific guidance
- capture path identity/cache, Unicode-safe parsing, hot-path
I/O/allocation, and cross-platform rules
- require tests to prove claimed read-count, cache-hit, and event-count
invariants
- wire the recurring checks into the Reviewer agent for every Rust
change

## Review retrospective

Recent feedback clustered around:
- normalized cache keys and caller-facing path preservation (#487, #490)
- Unicode-safe byte indexing and ASCII format handling (#493)
- proving optimization scope and read counts (#493)
- duplicate side effects and precise pattern semantics (#495)
- workflow assignment/merge postconditions, already addressed in #486

Fixes #496

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

Conda: conda-meta/history is read multiple times per env per find() call

3 participants