Project

General

Profile

Actions

Bug #21032

open

`Module#autoload?` is slow when `$LOAD_PATH` contains a relative path

Added by byroot (Jean Boussier) 3 days ago. Updated 2 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:120637]

Description

Reproduction script:

require 'benchmark'

$LOAD_PATH << 'relative-path'

autoload :FOO, '/tmp/foo.rb'

puts Benchmark.realtime {
  500_000.times do
    Object.autoload?(:FOO)
  end
}

The above takes 2.5 to 3 seconds on my machine, but just removing $LOAD_PATH << 'relative-path' make it complete in 50ms.
It's such a stark difference that I think it is a bug, and it cause Zeitwerk, a very popular gem, to be way slower than it should
when the load path contains relative paths.

I have a patch for it, that passes all tests, but I'd appreciate some eyes on it: https://github.com/ruby/ruby/pull/12562

cc @fxn

Updated by Eregon (Benoit Daloze) 3 days ago

For curiosity, what's adding a relative path in $LOAD_PATH? That sounds rather dubious/wrong.

Updated by byroot (Jean Boussier) 2 days ago

I dug more into this today, based on @nobu's review. autoload? isn't the only thing slowed down in such case.

Perhaps we should try to emit a performance warning when a relative path or non-string object is appended to $LOAD_PATH. That would at least make it easier to notice this issue.

The problem of course is that $LOAD_PATH is just a regular array, so there isn't a clean hook where to check for this.

Updated by Eregon (Benoit Daloze) 2 days ago

byroot (Jean Boussier) wrote in #note-2:

@fxn tracked it down to https://github.com/emailage/Emailage_Ruby/blob/64b9762cda7608ac1eeced2a85ad5f4b7919f4f0/lib/emailage.rb#L1, and yes that's an anti-pattern in my opinion too.

Right, that's just broken code. It would consider files under lib in $PWD for require which is wrong.

Perhaps we should try to emit a performance warning when a relative path or non-string object is appended to $LOAD_PATH. That would at least make it easier to notice this issue.

The problem of course is that $LOAD_PATH is just a regular array, so there isn't a clean hook where to check for this.

Maybe just warn on require or so, i.e. when noticing the path is relative, if it's too hard to notice when it's added?
I think there is also a cache for the expanded load path, maybe that could be a reasonable place to check.
It wouldn't immediately point at the culprit, but printing the $LOADED_FEATURES should help find it (maybe there should be a CLI flag/ENV var to print files as they are loaded, TruffleRuby has that).

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0