diff options
| author | MSP-Greg <MSP-Greg@users.noreply.github.com> | 2023-08-21 18:33:47 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-21 23:33:47 +0000 |
| commit | 788b03d5ba82fd8b35ce1fe2618ce6bacc648333 (patch) | |
| tree | e6fb84d186606ce6ad74b8beeb48cb182944c5cb | |
| parent | e517ba2e5b6434e7d2370de7703f481dcb8eecba (diff) | |
Re-apply "Ruby 3.2 - Speed up rebuilding the loaded feature index and realpath cache (#8023)" (#8252)
* Re-apply "Ruby 3.2 - Speed up rebuilding the loaded feature index and realpath cache (#8023)"
* [CI] mingw.yml - remove IBM437 encoding for test-all, use cmd shell for test & test-all
* Skip failing test on mingw with readline.so
Co-authored-by: nagachika <nagachika@ruby-lang.org>
---------
Co-authored-by: nagachika <nagachika@ruby-lang.org>
| -rw-r--r-- | .github/workflows/mingw.yml | 4 | ||||
| -rw-r--r-- | load.c | 47 | ||||
| -rw-r--r-- | test/excludes/TestReadline.rb | 4 | ||||
| -rw-r--r-- | vm.c | 2 | ||||
| -rw-r--r-- | vm_core.h | 1 |
5 files changed, 50 insertions, 8 deletions
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index ba3886218a..c8b53ad76b 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -139,12 +139,11 @@ jobs: run: | make test if: ${{matrix.test_task == 'check' || matrix.test_task == 'test'}} + shell: cmd - name: test-all timeout-minutes: 45 run: | - # Actions uses UTF8, causes test failures, similar to normal OS setup - chcp.com 437 make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }} env: RUBY_TESTOPTS: >- @@ -152,6 +151,7 @@ jobs: ${{ matrix.test-all-opts }} BUNDLER_VERSION: if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/')}} + shell: cmd - name: test-spec timeout-minutes: 10 @@ -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; @@ -675,6 +689,19 @@ rb_provide(const char *feature) NORETURN(static void load_failed(VALUE)); +static inline VALUE +realpath_internal_cached(VALUE hash, VALUE path) +{ + VALUE ret = rb_hash_aref(hash, path); + if(RTEST(ret)) { + return ret; + } + + VALUE realpath = rb_realpath_internal(Qnil, path, 1); + rb_hash_aset(hash, rb_fstring(path), rb_fstring(realpath)); + return realpath; +} + static inline void load_iseq_eval(rb_execution_context_t *ec, VALUE fname) { @@ -687,8 +714,12 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname) VALUE parser = rb_parser_new(); rb_parser_set_context(parser, NULL, FALSE); ast = (rb_ast_t *)rb_parser_load_file(parser, fname); + + rb_thread_t *th = rb_ec_thread_ptr(ec); + VALUE realpath_map = get_loaded_features_realpath_map(th->vm); + iseq = rb_iseq_new_top(&ast->body, rb_fstring_lit("<top (required)>"), - fname, rb_realpath_internal(Qnil, fname, 1), NULL); + fname, realpath_internal_cached(realpath_map, fname), NULL); rb_ast_dispose(ast); rb_vm_pop_frame(ec); RB_GC_GUARD(v); @@ -1161,6 +1192,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; @@ -1194,7 +1226,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa } #endif else if (RTEST(rb_hash_aref(realpaths, - realpath = rb_realpath_internal(Qnil, path, 1)))) { + realpath = realpath_internal_cached(realpath_map, path)))) { result = 0; } else { @@ -1252,7 +1284,8 @@ 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); } } ec->errinfo = saved.errinfo; @@ -1473,6 +1506,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); diff --git a/test/excludes/TestReadline.rb b/test/excludes/TestReadline.rb new file mode 100644 index 0000000000..706736f6f6 --- /dev/null +++ b/test/excludes/TestReadline.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: false +if /mingw/i.match?(RUBY_PLATFORM) + exclude(:test_input_metachar_multibyte, "failed with readline.so on MiNGW") +end @@ -2703,6 +2703,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); @@ -2794,6 +2795,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); @@ -680,6 +680,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 |
