diff options
author | Jeremy Evans <code@jeremyevans.net> | 2023-04-12 12:33:16 -0700 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2023-04-13 20:22:36 -0700 |
commit | 1f115f141dd17f75049a5e17107906c5bcc372e1 (patch) | |
tree | ee97dfc4e85959cf84b8cb2e048e21fcc9e8b784 /load.c | |
parent | 6beb755d810082ea3f557f54c687bc752a11cc7b (diff) |
Speed up rebuilding the loaded feature index
Rebuilding the loaded feature index slowed down with the bug fix
for #17885 in 79a4484a072e9769b603e7b4fbdb15b1d7eccb15. The
slowdown was extreme if realpath emulation was used, but even when
not emulated, it could be about 10x slower.
This adds loaded_features_realpath_map to rb_vm_struct. This is a
hidden hash mapping loaded feature paths to realpaths. When
rebuilding the loaded feature index, look at this hash to get
cached realpath values, and skip calling rb_check_realpath if a
cached value is found.
Fixes [Bug #19246]
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7699
Diffstat (limited to 'load.c')
-rw-r--r-- | load.c | 27 |
1 files changed, 23 insertions, 4 deletions
@@ -164,6 +164,12 @@ get_loaded_features_realpaths(rb_vm_t *vm) } static VALUE +get_loaded_features_realpath_map(rb_vm_t *vm) +{ + return vm->loaded_features_realpath_map; +} + +static VALUE get_LOADED_FEATURES(ID _x, VALUE *_y) { return get_loaded_features(GET_VM()); @@ -361,7 +367,10 @@ get_loaded_features_index(rb_vm_t *vm) st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0); VALUE realpaths = vm->loaded_features_realpaths; + VALUE realpath_map = vm->loaded_features_realpath_map; + VALUE previous_realpath_map = rb_hash_dup(realpath_map); rb_hash_clear(realpaths); + rb_hash_clear(realpath_map); features = vm->loaded_features; for (i = 0; i < RARRAY_LEN(features); i++) { VALUE entry, as_str; @@ -378,9 +387,14 @@ get_loaded_features_index(rb_vm_t *vm) long j = RARRAY_LEN(features); for (i = 0; i < j; i++) { VALUE as_str = rb_ary_entry(features, i); - VALUE realpath = rb_check_realpath(Qnil, as_str, NULL); - if (NIL_P(realpath)) realpath = as_str; - rb_hash_aset(realpaths, rb_fstring(realpath), Qtrue); + VALUE realpath = rb_hash_aref(previous_realpath_map, as_str); + if (NIL_P(realpath)) { + realpath = rb_check_realpath(Qnil, as_str, NULL); + if (NIL_P(realpath)) realpath = as_str; + realpath = rb_fstring(realpath); + } + rb_hash_aset(realpaths, realpath, Qtrue); + rb_hash_aset(realpath_map, as_str, realpath); } } return vm->loaded_features_index; @@ -1161,6 +1175,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa volatile VALUE saved_path; volatile VALUE realpath = 0; VALUE realpaths = get_loaded_features_realpaths(th->vm); + VALUE realpath_map = get_loaded_features_realpath_map(th->vm); volatile bool reset_ext_config = false; struct rb_ext_config prev_ext_config; @@ -1252,7 +1267,9 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa rb_provide_feature(th2->vm, path); VALUE real = realpath; if (real) { - rb_hash_aset(realpaths, rb_fstring(real), Qtrue); + real = rb_fstring(real); + rb_hash_aset(realpaths, real, Qtrue); + rb_hash_aset(realpath_map, path, real); } } ec->errinfo = saved.errinfo; @@ -1473,6 +1490,8 @@ Init_load(void) vm->loaded_features_index = st_init_numtable(); vm->loaded_features_realpaths = rb_hash_new(); rb_obj_hide(vm->loaded_features_realpaths); + vm->loaded_features_realpath_map = rb_hash_new(); + rb_obj_hide(vm->loaded_features_realpath_map); rb_define_global_function("load", rb_f_load, -1); rb_define_global_function("require", rb_f_require, 1); |