Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manually defining inception namespaces to skip autoload? call #308

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,16 @@ Both strings and `Pathname` objects are supported as arguments. The method raise
If you want to eager load a directory, `Zeitwerk::Loader#eager_load_dir` is more efficient than invoking `Zeitwerk::Loader#load_file` on its files.

<a id="markdown-reloading" name="reloading"></a>

#### Optimize performance by manually defining inceptions

In order to avoid the costly `autoload?` call on all the autoloaded definitions you can manually define a list of namespaces to be included as inceptions.
Use this as your own risk, note that after manually setting `manual_incepted_namespaces`, if you add a Gem which needs the inception you will need to include it in this list manually in order to have it working.

```ruby
loader.manual_incepted_namespaces = ['ActionCable']
```

### Reloading

<a id="markdown-configuration-and-usage" name="configuration-and-usage"></a>
Expand Down
17 changes: 14 additions & 3 deletions lib/zeitwerk/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -536,9 +536,20 @@ def all_dirs
autoloads[abspath] = cref
Registry.register_autoload(self, abspath)

# See why in the documentation of Zeitwerk::Registry.inceptions.
unless cref.autoload?
Registry.register_inception(cref.path, abspath, self)
# If manual incepted namespaces are present we skip the default behavior
# and we will only incept the manually defined namespaces for improved
# performance
if manual_incepted_namespaces.empty?
# This operation can impact performance in big codebases since it will
# be evaluated for every single auoloaded constant.
# See why in the documentation of Zeitwerk::Registry.inceptions.
unless cref.autoload?
Registry.register_inception(cref.path, abspath, self)
end
else
if manual_incepted_namespaces.include?(cref.cname.name)
Registry.register_inception(cref.path, abspath, self)
end
end
end

Expand Down
32 changes: 18 additions & 14 deletions lib/zeitwerk/loader/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ module Zeitwerk::Loader::Config
# @sig #call | #debug | nil
attr_accessor :logger

# @sig Set[String]
attr_accessor :manual_incepted_namespaces

# Absolute paths of the root directories, mapped to their respective root namespaces:
#
# "/Users/fxn/blog/app/channels" => Object,
Expand Down Expand Up @@ -84,20 +87,21 @@ module Zeitwerk::Loader::Config
private :on_unload_callbacks

def initialize
@inflector = Zeitwerk::Inflector.new
@logger = self.class.default_logger
@tag = SecureRandom.hex(3)
@initialized_at = Time.now
@roots = {}
@ignored_glob_patterns = Set.new
@ignored_paths = Set.new
@collapse_glob_patterns = Set.new
@collapse_dirs = Set.new
@eager_load_exclusions = Set.new
@reloading_enabled = false
@on_setup_callbacks = []
@on_load_callbacks = {}
@on_unload_callbacks = {}
@inflector = Zeitwerk::Inflector.new
@logger = self.class.default_logger
@manual_incepted_namespaces = Set.new
@tag = SecureRandom.hex(3)
@initialized_at = Time.now
@roots = {}
@ignored_glob_patterns = Set.new
@ignored_paths = Set.new
@collapse_glob_patterns = Set.new
@collapse_dirs = Set.new
@eager_load_exclusions = Set.new
@reloading_enabled = false
@on_setup_callbacks = []
@on_load_callbacks = {}
@on_unload_callbacks = {}
end

# Pushes `path` to the list of root directories.
Expand Down
Loading