зеркало из https://github.com/github/ruby.git
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.
This commit is contained in:
Родитель
d516910b61
Коммит
abfac2222b
22
load.c
22
load.c
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче