Release gvl while doing (f)stat

At the moment rb_stat function is blocking. This patch changes the
behaviour to release the gvl while waiting for OS to return from
f(stat).

There is behaviour impact, but not significant (times are for 100000
iterations):

   $ ~/releaseruby_patch/bin/ruby bench.rb
Rehearsal ------------------------------------------------
File.exist?:   0.036412   0.056616   0.093028 (  0.093075)
--------------------------------------- total: 0.093028sec

                   user     system      total        real
File.exist?:   0.042953   0.049783   0.092736 (  0.092804)

   $ ~/releaseruby_no_patch/bin/ruby bench.rb
Rehearsal ------------------------------------------------
File.exist?:   0.056094   0.026293   0.082387 (  0.082389)
--------------------------------------- total: 0.082387sec

                   user     system      total        real
File.exist?:   0.037250   0.046702   0.083952 (  0.083956)

Based on the patch by Wolf <wolf@wolfsden.cz> at [ruby-core:83012],
with using `rb_thread_io_blocking_region` for `fstat`.
[Bug #13941]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-09-26 04:13:37 +00:00
Родитель c57eb143ec
Коммит 66c9d4f55e
2 изменённых файлов: 33 добавлений и 2 удалений

Просмотреть файл

@ -1757,6 +1757,7 @@ file.$(OBJEXT): {$(VPATH)}onigmo.h
file.$(OBJEXT): {$(VPATH)}oniguruma.h
file.$(OBJEXT): {$(VPATH)}st.h
file.$(OBJEXT): {$(VPATH)}subst.h
file.$(OBJEXT): {$(VPATH)}thread.h
file.$(OBJEXT): {$(VPATH)}util.h
gc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
gc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h

34
file.c
Просмотреть файл

@ -27,6 +27,7 @@
#include "internal.h"
#include "ruby/io.h"
#include "ruby/util.h"
#include "ruby/thread.h"
#include "dln.h"
#include "encindex.h"
@ -1022,21 +1023,50 @@ rb_stat_inspect(VALUE self)
return str;
}
typedef struct no_gvl_stat_data {
struct stat *st;
union {
const char *path;
int fd;
} file;
} no_gvl_stat_data;
static VALUE
no_gvl_fstat(void *data)
{
no_gvl_stat_data *arg = data;
return (VALUE)fstat(arg->file.fd, arg->st);
}
static void *
no_gvl_stat(void * data)
{
no_gvl_stat_data *arg = data;
return (void *)(VALUE)STAT(arg->file.path, arg->st);
}
static int
rb_stat(VALUE file, struct stat *st)
{
VALUE tmp;
VALUE result;
no_gvl_stat_data data;
data.st = st;
tmp = rb_check_convert_type_with_id(file, T_FILE, "IO", idTo_io);
if (!NIL_P(tmp)) {
rb_io_t *fptr;
GetOpenFile(tmp, fptr);
return fstat(fptr->fd, st);
data.file.fd = fptr->fd;
result = rb_thread_io_blocking_region(no_gvl_fstat, &data, fptr->fd);
return (int)result;
}
FilePathValue(file);
file = rb_str_encode_ospath(file);
return STAT(StringValueCStr(file), st);
data.file.path = StringValueCStr(file);
result = (VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data, RUBY_UBF_IO, NULL);
return (int)result;
}
#ifdef _WIN32