From fff4e0a8f0fe537089e1a016ad3b09cde67bb39d Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Wed, 21 Aug 2024 23:31:43 -0700 Subject: [PATCH] Speed up Tap#cask_files_by_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is most noticeable when you have a large local tap and it ends up taking a nontrivial percentage of the overall run time for simple commands like `brew info gimp`. The improvement here is to just create paths later on in the loop which copies what we already do for formulae. See b1ddb05 ```console $ hyperfine --parameter-list branch master,speed-up-cask-files-by-name --warmup 5 --setup 'git switch {branch}' 'brew info gimp' Benchmark 1: brew info gimp (branch = master) Time (mean ± σ): 2.737 s ± 0.010 s [User: 1.958 s, System: 0.732 s] Range (min … max): 2.720 s … 2.748 s 10 runs Benchmark 2: brew info gimp (branch = speed-up-cask-files-by-name) Time (mean ± σ): 2.597 s ± 0.017 s [User: 1.828 s, System: 0.724 s] Range (min … max): 2.577 s … 2.624 s 10 runs Summary brew info gimp (branch = speed-up-cask-files-by-name) ran 1.05 ± 0.01 times faster than brew info gimp (branch = master) ``` --- Library/Homebrew/tap.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 8ed3436d69..b4e7ab8211 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -1427,12 +1427,16 @@ class CoreCaskTap < AbstractCoreTap def cask_files_by_name return super if Homebrew::EnvConfig.no_install_from_api? - @cask_files_by_name ||= Homebrew::API::Cask.all_casks.each_with_object({}) do |item, hash| - name, cask_hash = item - # If there's more than one item with the same path: use the longer one to prioritise more specific results. - existing_path = hash[name] - new_path = path/cask_hash["ruby_source_path"] - hash[name] = new_path if existing_path.nil? || existing_path.to_s.length < new_path.to_s.length + @cask_files_by_name ||= begin + tap_path = path.to_s + Homebrew::API::Cask.all_casks.each_with_object({}) do |item, hash| + name, cask_hash = item + # If there's more than one item with the same path: use the longer one to prioritise more specific results. + existing_path = hash[name] + # Pathname equivalent is slow in a tight loop + new_path = File.join(tap_path, cask_hash.fetch("ruby_source_path")) + hash[name] = Pathname(new_path) if existing_path.nil? || existing_path.to_s.length < new_path.length + end end end