Skip to content

Commit

Permalink
Speed up rebuilding the loaded feature index
Browse files Browse the repository at this point in the history
Rebuilding the loaded feature index slowed down with the bug fix
for #17885 in 79a4484.  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]
  • Loading branch information
jeremyevans committed Apr 14, 2023
1 parent 6beb755 commit 1f115f1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 4 deletions.
27 changes: 23 additions & 4 deletions load.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ get_loaded_features_realpaths(rb_vm_t *vm)
return vm->loaded_features_realpaths;
}

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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2699,6 +2699,7 @@ rb_vm_update_references(void *ptr)
vm->loaded_features = rb_gc_location(vm->loaded_features);
vm->loaded_features_snapshot = rb_gc_location(vm->loaded_features_snapshot);
vm->loaded_features_realpaths = rb_gc_location(vm->loaded_features_realpaths);
vm->loaded_features_realpath_map = rb_gc_location(vm->loaded_features_realpath_map);
vm->top_self = rb_gc_location(vm->top_self);
vm->orig_progname = rb_gc_location(vm->orig_progname);

Expand Down Expand Up @@ -2790,6 +2791,7 @@ rb_vm_mark(void *ptr)
rb_gc_mark_movable(vm->loaded_features);
rb_gc_mark_movable(vm->loaded_features_snapshot);
rb_gc_mark_movable(vm->loaded_features_realpaths);
rb_gc_mark_movable(vm->loaded_features_realpath_map);
rb_gc_mark_movable(vm->top_self);
rb_gc_mark_movable(vm->orig_progname);
RUBY_MARK_MOVABLE_UNLESS_NULL(vm->coverages);
Expand Down
1 change: 1 addition & 0 deletions vm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ typedef struct rb_vm_struct {
VALUE loaded_features;
VALUE loaded_features_snapshot;
VALUE loaded_features_realpaths;
VALUE loaded_features_realpath_map;
struct st_table *loaded_features_index;
struct st_table *loading_table;
#if EXTSTATIC
Expand Down

0 comments on commit 1f115f1

Please sign in to comment.