Skip to content

perf/sorbet: skip sorbet-runtime dispatch when runtime disabled (~6-8% faster)#22978

Merged
dduugg merged 1 commit into
mainfrom
tnochecks-noop-experiment
Jul 6, 2026
Merged

perf/sorbet: skip sorbet-runtime dispatch when runtime disabled (~6-8% faster)#22978
dduugg merged 1 commit into
mainfrom
tnochecks-noop-experiment

Conversation

@dduugg

@dduugg dduugg commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

When $HOMEBREW_SORBET_RUNTIME is unset (every user except CI and developers running brew tests/test-bot), standalone/sorbet.rb prepends TNoChecks so that T.let/T.cast/T.bind/T.assert_type! default to checked: false. Each call still pays two keyword-argument dispatches, though: TNoChecks#let and then super into sorbet-runtime, which immediately returns via return value unless checked.

These methods are called often enough for that dispatch to be measurable: for example, EagerInitializeExtension#initialize runs six T.lets on every Pathname allocation. In a stackprof profile of brew upgrade --dry-run taken with $HOMEBREW_SORBET_RUNTIME unset, TNoChecks#let alone accounted for ~4% of samples.

Changes

Make the TNoChecks overrides return the value directly instead of calling super, eliminating the second dispatch and sorbet-runtime's disabled-check branch entirely.

Behavior is unchanged:

  • The runtime-enabled branch ($HOMEBREW_SORBET_RUNTIME set, as used by brew tests and brew test-bot) is untouched.
  • No Homebrew code passes checked: true explicitly, so nothing relied on opting back into validation while the runtime is disabled.
  • The checked: keyword remains accepted so any explicit checked: call sites keep working.

Benchmarks (Hyperfine, 10 runs each, warmup 2, HOMEBREW_SORBET_RUNTIME unset, clean trees, on the top 3 commands from the last 365 days of analytics):

Command Before After Change
brew upgrade --dry-run (3rd most-run, ~30 outdated) 4.792 s ± 0.153 s 4.399 s ± 0.088 s ~8% decrease
brew install <installed formula> (2nd most-run) 611.0 ms ± 30.4 ms 566.4 ms ± 11.6 ms ~7% decrease
brew config (4th most-run) 755.9 ms ± 29.9 ms 709.6 ms ± 17.2 ms ~6% decrease

No new unit tests: the changed branch only loads when $HOMEBREW_SORBET_RUNTIME is unset, and brew tests always sets it, so the no-op path cannot be exercised from the test suite.


  • Have you followed our Contributing guidelines?
  • Have you checked for other open Pull Requests for the same change?
  • Have you explained what your changes do? Performance claims (e.g. "this is faster") must include Hyperfine benchmarks.
  • Have you explained why you'd like these changes included, not just what they do?
  • For bug fixes, have you given step-by-step brew commands to reproduce the bug?
  • Have you written new tests (excluding integration tests)? Here's an example.
  • Have you successfully run brew lgtm (style, typechecking and tests) locally?

  • AI was used to generate or assist with generating this PR.

Claude Code was used to profile representative commands with stackprof, identify the double dispatch, implement the change and run the benchmarks. Verified by smoke-testing commands with $HOMEBREW_SORBET_RUNTIME both set and unset, checking there are no explicit checked: true call sites in the codebase, clean-tree before/after Hyperfine benchmarks and running brew lgtm locally.


@MikeMcQuaid MikeMcQuaid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good idea!

@dduugg dduugg marked this pull request as ready for review July 6, 2026 14:48
Copilot AI review requested due to automatic review settings July 6, 2026 14:48

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 optimizes Homebrew’s Sorbet runtime-disabled path by reducing overhead in frequently-called T.* helpers, aiming to speed up common brew commands when $HOMEBREW_SORBET_RUNTIME is unset (the default for most users).

Changes:

  • Updates Library/Homebrew/standalone/sorbet.rb to avoid unnecessary dispatch into sorbet-runtime for T.cast, T.let, T.bind, and T.assert_type! when runtime checking is disabled.
  • Keeps the runtime-enabled ($HOMEBREW_SORBET_RUNTIME set) behavior unchanged.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Library/Homebrew/standalone/sorbet.rb
@dduugg dduugg added this pull request to the merge queue Jul 6, 2026
Merged via the queue into main with commit bd67a64 Jul 6, 2026
44 checks passed
@dduugg dduugg deleted the tnochecks-noop-experiment branch July 6, 2026 16:57
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.

3 participants