Skip to content

gix-blame: Replace BTreeMap by SmallVec #1945

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 11, 2025

Conversation

cruessler
Copy link
Contributor

This PR increases gix-blame’s performance by replacing suspects: BTreeMap with suspects: SmallVec.

A SmallVec provides a better trade-off with respect to performance than a BTreeMap because suspects in most cases only contains 1 item. The cost of calling BTreeMap::insert and BTreeMap::remove becomes noticeable in profiling the longer a blame’s history gets and the more hunks a file is split into.

For smaller blames, the benefits are negligible, but for larger repos and larger files they are so significant that I’m worried I might have made a mistake trying to measure them. 😄

The following benchmarks compare this PR against main.

❯ env GIT_DIR="$HOME/github/Byron/gitoxide/.git" hyperfine --warmup 1 --export-markdown results.md '$HOME/github/Byron/gitoxide/target/profiling/gix blame Cargo.lock' '$HOME/worktrees/gitoxide/branch-6/target/profiling/gix blame Cargo.lock'
Benchmark 1: $HOME/github/Byron/gitoxide/target/profiling/gix blame Cargo.lock
  Time (mean ± σ):      1.482 s ±  0.009 s    [User: 1.284 s, System: 0.192 s]
  Range (min … max):    1.468 s …  1.499 s    10 runs

Benchmark 2: $HOME/worktrees/gitoxide/branch-6/target/profiling/gix blame Cargo.lock
  Time (mean ± σ):      1.269 s ±  0.008 s    [User: 1.078 s, System: 0.185 s]
  Range (min … max):    1.261 s …  1.289 s    10 runs

Summary
  '$HOME/worktrees/gitoxide/branch-6/target/profiling/gix blame Cargo.lock' ran
    1.17 ± 0.01 times faster than '$HOME/github/Byron/gitoxide/target/profiling/gix blame Cargo.lock'

❯ env GIT_DIR="$HOME/github/torvalds/linux/.git" hyperfine --warmup 1 --export-markdown results.md '$HOME/github/Byron/gitoxide/target/profiling/gix blame CREDITS' '$HOME/worktrees/gitoxide/branch-6/target/profiling/gix blame CREDITS'
Benchmark 1: $HOME/github/Byron/gitoxide/target/profiling/gix blame CREDITS
  Time (mean ± σ):      2.207 s ±  0.026 s    [User: 2.026 s, System: 0.174 s]
  Range (min … max):    2.179 s …  2.261 s    10 runs

Benchmark 2: $HOME/worktrees/gitoxide/branch-6/target/profiling/gix blame CREDITS
  Time (mean ± σ):      1.591 s ±  0.015 s    [User: 1.411 s, System: 0.174 s]
  Range (min … max):    1.576 s …  1.629 s    10 runs

Summary
  '$HOME/worktrees/gitoxide/branch-6/target/profiling/gix blame CREDITS' ran
    1.39 ± 0.02 times faster than '$HOME/github/Byron/gitoxide/target/profiling/gix blame CREDITS'

A `SmallVec` provides a better trade-off with respect to performance
than a `BTreeMap` because `suspects` in most cases only contains 1 item.
The cost of calling `BTreeMap::insert` and `BTreeMap::remove` becomes
noticeable in profiling the longer a blame’s history gets and the more
hunks a file is split into.
Copy link
Member

@Byron Byron left a comment

Choose a reason for hiding this comment

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

🔥🚀❤️

@Byron Byron merged commit c75bc44 into GitoxideLabs:main Apr 11, 2025
22 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