diff options
author | krk <keremkat@gmail.com> | 2023-07-03 00:00:00 +0000 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-07-10 18:05:19 +0900 |
commit | abfac2222bd51a03ec11b64f4770179cb6d06515 (patch) | |
tree | 00b77efa1ce6d9f583fb536b9c7b499b00d21d06 /load.c | |
parent | d516910b61586fc6de676cf75930788594afe479 (diff) |
Add a realpath cache to reduce number of syscalls.
Number of lstat and stat syscalls for each 'require'd file is doubled,
because rb_realpath_internal is called from two places with the same
arguments in require_internal; once for checking the realpaths cache,
and once in load_iseq_eval when iseq is not found.
Introduce rb_realpath_internal_cached function to reuse the realpath_map
cache which memoizes rb_realpath_internal function, leading to less
syscalls and increased startup performance depending on the cost of the syscalls
in a particular environment.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/8017
Diffstat (limited to 'load.c')
-rw-r--r-- | load.c | 22 |
1 files changed, 19 insertions, 3 deletions
@@ -689,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) { @@ -701,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); @@ -1208,7 +1225,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa result = TAG_RETURN; } else if (RTEST(rb_hash_aref(realpaths, - realpath = rb_realpath_internal(Qnil, path, 1)))) { + realpath = realpath_internal_cached(realpath_map, path)))) { result = 0; } else { @@ -1268,7 +1285,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa if (real) { real = rb_fstring(real); rb_hash_aset(realpaths, real, Qtrue); - rb_hash_aset(realpath_map, path, real); } } ec->errinfo = saved.errinfo; |