From 683ae7ff53052d365dcbe4aba8d4d5bb7b6026b5 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 21 Jan 2021 12:34:04 +0000 Subject: [PATCH] Add HOMEBREW_BOOTSNAP to optionally use Bootsnap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > Bootsnap is a library that plugs into Ruby, with optional support > for ActiveSupport and YAML, to optimize and cache expensive > computations. https://github.com/Shopify/bootsnap For our case that translates to "repeated calls to `brew` have reductions in the time spend `require`ing speeding up the process boot time". For example: ``` $ hyperfine --warmup=2 "unset HOMEBREW_BOOTSNAP; brew info wget" "export HOMEBREW_BOOTSNAP=1; brew info wget" Benchmark #1: unset HOMEBREW_BOOTSNAP; brew info wget Time (mean ± σ): 2.417 s ± 0.032 s [User: 659.0 ms, System: 855.5 ms] Range (min … max): 2.382 s … 2.464 s 10 runs Benchmark #2: export HOMEBREW_BOOTSNAP=1; brew info wget Time (mean ± σ): 1.862 s ± 0.064 s [User: 425.3 ms, System: 566.8 ms] Range (min … max): 1.736 s … 1.952 s 10 runs Summary 'export HOMEBREW_BOOTSNAP=1; brew info wget' ran 1.30 ± 0.05 times faster than 'unset HOMEBREW_BOOTSNAP; brew info wget' ``` --- .gitignore | 2 ++ Library/.rubocop.yml | 1 + Library/Homebrew/Gemfile | 1 + Library/Homebrew/bootsnap.rb | 20 ++++++++++++++++++++ Library/Homebrew/global.rb | 4 ++-- Library/Homebrew/load_path.rb | 8 ++++++-- 6 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 Library/Homebrew/bootsnap.rb diff --git a/.gitignore b/.gitignore index c85e45806b..1336c48acd 100644 --- a/.gitignore +++ b/.gitignore @@ -85,6 +85,7 @@ # Ignore dependencies we don't wish to vendor **/vendor/bundle/ruby/*/gems/ast-*/ +**/vendor/bundle/ruby/*/gems/bootsnap-*/ **/vendor/bundle/ruby/*/gems/bundler-*/ **/vendor/bundle/ruby/*/gems/byebug-*/ **/vendor/bundle/ruby/*/gems/coderay-*/ @@ -105,6 +106,7 @@ **/vendor/bundle/ruby/*/gems/mime-types-*/ **/vendor/bundle/ruby/*/gems/mini_portile2-*/ **/vendor/bundle/ruby/*/gems/minitest-*/ +**/vendor/bundle/ruby/*/gems/msgpack-*/ **/vendor/bundle/ruby/*/gems/mustache-*/ **/vendor/bundle/ruby/*/gems/net-http-digest_auth-*/ **/vendor/bundle/ruby/*/gems/net-http-persistent-*/ diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index aacef7a6be..f0a50eae84 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -370,6 +370,7 @@ Sorbet/FalseSigil: - "/**/{Formula,Casks}/*.rb" - "**/{Formula,Casks}/*.rb" - "Homebrew/test/**/Casks/**/*.rb" + - "Homebrew/bootsnap.rb" Sorbet/StrictSigil: Enabled: true diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index afd899baf0..cfc9287a89 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -3,6 +3,7 @@ source "https://rubygems.org" # installed gems (should all be require: false) +gem "bootsnap", require: false if ENV["HOMEBREW_BOOTSNAP"] gem "byebug", require: false gem "codecov", require: false gem "nokogiri", require: false diff --git a/Library/Homebrew/bootsnap.rb b/Library/Homebrew/bootsnap.rb new file mode 100644 index 0000000000..026e54cfca --- /dev/null +++ b/Library/Homebrew/bootsnap.rb @@ -0,0 +1,20 @@ +# typed: ignore +# frozen_string_literal: true + +# TODO: make this `typed: true` when HOMEBREW_BOOTSNAP is enabled by +# default and/or we vendor bootsnap and the RBI file. + +raise "Needs HOMEBREW_BOOTSNAP!" unless ENV["HOMEBREW_BOOTSNAP"] + +require "rubygems" +require "bootsnap" + +Bootsnap.setup( + cache_dir: "#{ENV["HOMEBREW_TEMP"]}/homebrew-bootsnap", + development_mode: false, # TODO: use ENV["HOMEBREW_DEVELOPER"]?, + load_path_cache: true, + autoload_paths_cache: true, + disable_trace: true, + compile_cache_iseq: true, + compile_cache_yaml: true, +) diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index 78a8db4790..fad56654d5 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -1,6 +1,8 @@ # typed: false # frozen_string_literal: true +require_relative "load_path" + require "English" require "json" require "json/add/exception" @@ -14,8 +16,6 @@ require "rbconfig" RUBY_PATH = Pathname.new(RbConfig.ruby).freeze RUBY_BIN = RUBY_PATH.dirname.freeze -require_relative "load_path" - require "rubygems" # Only require "core_ext" here to ensure we're only requiring the minimum of # what we need. diff --git a/Library/Homebrew/load_path.rb b/Library/Homebrew/load_path.rb index 258265213c..72fa1c3a37 100644 --- a/Library/Homebrew/load_path.rb +++ b/Library/Homebrew/load_path.rb @@ -9,5 +9,9 @@ $LOAD_PATH.push HOMEBREW_LIBRARY_PATH.to_s require "vendor/bundle/bundler/setup" -$LOAD_PATH.select! { |d| Pathname(d).directory? } -$LOAD_PATH.uniq! +if ENV["HOMEBREW_BOOTSNAP"] + require "bootsnap" +else + $LOAD_PATH.select! { |d| Pathname(d).directory? } + $LOAD_PATH.uniq! +end