Skip to content

Replace pmap gem with pure-Ruby thread pool#14

Merged
wteuber merged 1 commit into
masterfrom
refactor/drop-pmap-dependency
Jun 22, 2026
Merged

Replace pmap gem with pure-Ruby thread pool#14
wteuber merged 1 commit into
masterfrom
refactor/drop-pmap-dependency

Conversation

@wteuber

@wteuber wteuber commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Summary

git_report's only dependency was the pmap gem, used for parallel map/each over authors, emails, and file slices. This replaces it with a small in-tree helper, Git::Parallel, built entirely on the Ruby standard library. The tool now runs on stock Ruby (including the macOS system Ruby) with nothing to install.

What changed

  • lib/git/parallel.rb (new) — a bounded worker pool providing pmap/peach. MAX_THREADS = 64 matches pmap 1.1.1's historical default, so throughput on large repos is unchanged. The cap is essential: a naive one-thread-per-element version would spawn thousands of concurrent git subprocesses on a large repo (a fork bomb). Workers drain a pre-filled queue and exit when empty; Thread#value propagates the first worker exception to the caller.
  • lib/git/author.rb+LOC/-LOC now accumulate on the main thread after the parallel blocks return, fixing a latent cross-thread += race that existed under the old pmap usage too.
  • bin/git_report — removed the gem-vendoring / first-run gem install machinery that existed solely to install pmap. The launcher is now a few lines.
  • Gemfile — removed gem 'pmap'; the project is now dependency-free.
  • README + smoke-test comments — updated to reflect zero dependencies.

Verification

  • ✅ Smoke test passes on Ruby 3.4 (2 runs, 12 assertions, 0 failures)
  • ✅ Runs on stock macOS system Ruby 2.6 with no gems installed
  • ✅ RuboCop clean (2.6 target, 7 files, no offenses)
  • ✅ 5000-item stress test confirms peak concurrency never exceeds the 64-thread cap, result order is preserved, and exceptions propagate cleanly
  • ✅ Output matches the previous pmap-based version

git_report's only dependency was the pmap gem, used for parallel `map`/`each`
over authors, emails, and file slices. Replace it with a small in-tree helper
(Git::Parallel) built on the standard library, so the tool now runs on stock
Ruby with no gems to install.

- Add lib/git/parallel.rb: a bounded worker pool (MAX_THREADS = 64, matching
  pmap's historical default) providing pmap/peach. The cap is essential --
  one thread per author would spawn thousands of git subprocesses on large
  repositories. Workers drain a pre-filled queue and exit when empty;
  Thread#value propagates the first worker exception to the caller.
- author.rb: accumulate +LOC/-LOC on the main thread after the parallel
  blocks return, fixing a latent cross-thread `+=` race.
- bin/git_report: drop the gem-vendoring/first-run install machinery that
  existed solely to install pmap; the launcher is now a few lines.
- Gemfile: remove `gem 'pmap'`; keep it dependency-free.
- Update README and smoke-test comments to reflect zero dependencies.

Verified: smoke test passes on Ruby 3.4, runs on stock macOS Ruby 2.6 with no
gems, RuboCop clean, and a 5000-item stress test confirms concurrency never
exceeds the 64-thread cap.
@wteuber wteuber merged commit fb4ca56 into master Jun 22, 2026
6 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.

1 participant