[前][次][番号順一覧][スレッド一覧]

ruby-changes:62445

From: Jean <ko1@a...>
Date: Fri, 31 Jul 2020 21:08:11 +0900 (JST)
Subject: [ruby-changes:62445] 76722c4928 (master): [rubygems/rubygems] Optimize Gem.already_loaded?

https://git.ruby-lang.org/ruby.git/commit/?id=76722c4928

From 76722c4928d92fa6cc4a927203eab8a036516e23 Mon Sep 17 00:00:00 2001
From: Jean Boussier <jean.boussier@g...>
Date: Mon, 6 Jul 2020 15:18:05 +0200
Subject: [rubygems/rubygems] Optimize Gem.already_loaded?

Profiling a simple `ruby -e '1'` I see:

```
==================================
  Mode: wall(10)
  Samples: 3414 (55.10% miss rate)
  GC: 856 (25.07%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
       689  (20.2%)         669  (19.6%)     Gem.already_loaded?
       462  (13.5%)         462  (13.5%)     (marking)
       393  (11.5%)         393  (11.5%)     (sweeping)
       815  (23.9%)         365  (10.7%)     Gem::Specification.load
      1050  (30.8%)         156   (4.6%)     Gem.register_default_spec
       100   (2.9%)          84   (2.5%)     Gem::Specification#files
        64   (1.9%)          64   (1.9%)     Gem::BasicSpecification#internal_init
       136   (4.0%)          59   (1.7%)     <top (required)>
      2312  (67.7%)          58   (1.7%)     <top (required)>
        57   (1.7%)          57   (1.7%)     RbConfig.expand
        81   (2.4%)          55   (1.6%)     Gem::Requirement.parse
       191   (5.6%)          51   (1.5%)     <top (required)>
       128   (3.7%)          47   (1.4%)     Gem::Requirement#initialize
        41   (1.2%)          41   (1.2%)     Gem.suffix_regexp
       229   (6.7%)          35   (1.0%)     <module:Gem>
       260   (7.6%)          34   (1.0%)     Kernel#require
```

So clearly `Gem.already_loaded?` is a major hotspot.

After this optimization, it's down to:
```
==================================
  Mode: wall(10)
  Samples: 2653 (58.21% miss rate)
  GC: 718 (27.06%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
       416  (15.7%)         416  (15.7%)     (marking)
       715  (27.0%)         312  (11.8%)     Gem::Specification.load
       299  (11.3%)         299  (11.3%)     (sweeping)
       279  (10.5%)         279  (10.5%)     Gem.already_loaded?
       564  (21.3%)         106   (4.0%)     Gem.register_default_spec
        95   (3.6%)          80   (3.0%)     Gem::Specification#files
        72   (2.7%)          72   (2.7%)     Gem::BasicSpecification#internal_init
       129   (4.9%)          58   (2.2%)     <top (required)>
        53   (2.0%)          53   (2.0%)     RbConfig.expand
      1697  (64.0%)          52   (2.0%)     <top (required)>
        68   (2.6%)          49   (1.8%)     Gem::Requirement.parse
       183   (6.9%)          48   (1.8%)     <top (required)>
       112   (4.2%)          44   (1.7%)     Gem::Requirement#initialize
       220   (8.3%)          33   (1.2%)     <module:Gem>
       250   (9.4%)          32   (1.2%)     Kernel#require
```

The idea is that the vast majority of the time `already_loaded?` won't match
anything. So by first looking for candidate paths that `end_with?` the file we
look for, we save `default_gem_load_paths.size` iterations and string concatenations.

https://github.com/rubygems/rubygems/commit/c60ce88d49

diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index e72d62b..8e23c32 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1300,8 +1300,8 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} https://github.com/ruby/ruby/blob/trunk/lib/rubygems.rb#L1300
     private
 
     def already_loaded?(file)
-      default_gem_load_paths.find do |load_path_entry|
-        $LOADED_FEATURES.include?("#{load_path_entry}/#{file}")
+      $LOADED_FEATURES.any? do |feature_path|
+        feature_path.end_with?(file) && default_gem_load_paths.any? {|load_path_entry| feature_path == "#{load_path_entry}/#{file}" }
       end
     end
 
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]