This is an idea borrowed from Ruby 2.0.0, whereby the short names
of loaded features are held in an internal structure and used as
a first-line cache to avoid re-searching for re-required files.
Before this patch, in both JRuby and MRI, re-required files had to
do a full load path search every time because the loaded features
list only held the full canonical paths, which are only available
after searching for the proper load path entry under which the
file exists. With the patch in place, re-required files will
usually be immediately found in the cache.
The population and invalidation of the cache proceeds as follows:
* A reference is held to a dup of the loaded features array. When
this reference is captured.
* When adding a new feature to loaded features, we re-capture
the dup'ed features array and add the short name to a separate
* As long as the dup'ed features array is non-null and matches
the current loaded features array, we know we can safely use the
loaded features index.
* When the dup'ed features array does not match, we clear the
loaded features index and start populating it anew. Since most
typical Ruby code does not modify the loaded features array
directly, this should be rare.
Numbers with and without this change show the performance gained.
The following benchmark populates load path with 1000 entries and
requires the same file 1000 times.
system ~/projects/jruby $ rvm jruby do jruby bench_loaded_features.rb 1000 1000
8.110000 3.880000 11.990000 ( 9.708000)
system ~/projects/jruby $ jruby bench_loaded_features.rb 1000 1000
0.990000 0.050000 1.040000 ( 0.324000)