From 901c0b728d0011e0384f78d7a7d640dda980bc83 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Tue, 31 May 2022 16:00:43 +0200 Subject: [PATCH] Add Bootsnap.unload_cache! --- CHANGELOG.md | 3 +++ lib/bootsnap.rb | 4 ++++ lib/bootsnap/load_path_cache.rb | 16 +++++++++++++++- .../load_path_cache/core_ext/kernel_require.rb | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc188568..30f7f600 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ People still using the classic autoloader might want to stick to `bootsnap 1.12`. +* Add `Bootsnap.unload_cache!`. Applications can call it at the end of their boot sequence when they know + no more code will be loaded to reclaim a bit of memory. + # 1.12.0 * `bootsnap precompile` CLI will now also precompile `Rakefile` and `.rake` files. diff --git a/lib/bootsnap.rb b/lib/bootsnap.rb index 5aee9629..d5490f3a 100644 --- a/lib/bootsnap.rb +++ b/lib/bootsnap.rb @@ -76,6 +76,10 @@ def setup( ) end + def self.unload_cache! + LoadPathCache.unload! + end + def iseq_cache_supported? return @iseq_cache_supported if defined? @iseq_cache_supported diff --git a/lib/bootsnap/load_path_cache.rb b/lib/bootsnap/load_path_cache.rb index 05e9d30f..30ced18f 100644 --- a/lib/bootsnap/load_path_cache.rb +++ b/lib/bootsnap/load_path_cache.rb @@ -21,8 +21,12 @@ module LoadPathCache CACHED_EXTENSIONS = DLEXT2 ? [DOT_RB, DLEXT, DLEXT2] : [DOT_RB, DLEXT] + @enabled = false + class << self - attr_reader(:load_path_cache, :loaded_features_index) + attr_reader(:load_path_cache, :loaded_features_index, :enabled) + alias_method :enabled?, :enabled + remove_method(:enabled) def setup(cache_path:, development_mode:) unless supported? @@ -35,10 +39,20 @@ def setup(cache_path:, development_mode:) @loaded_features_index = LoadedFeaturesIndex.new @load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode) + @enabled = true require_relative("load_path_cache/core_ext/kernel_require") require_relative("load_path_cache/core_ext/loaded_features") end + def unload! + @enabled = false + @loaded_features_index = nil + @realpath_cache = nil + @load_path_cache = nil + ChangeObserver.unregister($LOAD_PATH) + ::Kernel.alias_method(:require_relative, :require_relative_without_bootsnap) + end + def supported? RUBY_ENGINE == "ruby" && RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/ diff --git a/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb b/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb index 8785f446..034a1ff5 100644 --- a/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +++ b/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb @@ -6,6 +6,8 @@ module Kernel alias_method(:require_without_bootsnap, :require) def require(path) + return require_without_bootsnap(path) unless Bootsnap::LoadPathCache.enabled? + string_path = Bootsnap.rb_get_path(path) return false if Bootsnap::LoadPathCache.loaded_features_index.key?(string_path)