mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
File#rename releases GVL
rename(2) requires two pathname resolution operations which can take considerable time on slow filesystems, release the GVL so operations on other threads may proceed. On fast, local filesystems, this change results in some slowdown as shown by the new benchmark. I consider the performance trade off acceptable as cases are avoided. benchmark results: minimum results in each 3 measurements. Execution time (sec) name trunk built file_rename 2.648 2.804 Speedup ratio: compare with the result of `trunk' (greater is better) name built file_rename 0.944 * file.c (no_gvl_rename): new function (rb_file_s_rename): release GVL for renames * benchmark/bm_file_rename.rb: new benchmark git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60088 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f01846cdc8
commit
e552afc30e
2 changed files with 29 additions and 4 deletions
11
benchmark/bm_file_rename.rb
Normal file
11
benchmark/bm_file_rename.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
# rename file
|
||||
require 'tempfile'
|
||||
|
||||
max = 100_000
|
||||
tmp = [ Tempfile.new('rename-a'), Tempfile.new('rename-b') ]
|
||||
a, b = tmp.map { |x| x.path }
|
||||
max.times do
|
||||
File.rename(a, b)
|
||||
File.rename(b, a)
|
||||
end
|
||||
tmp.each { |t| t.close! }
|
22
file.c
22
file.c
|
@ -2873,6 +2873,19 @@ rb_file_s_unlink(int argc, VALUE *argv, VALUE klass)
|
|||
return apply2files(unlink_internal, argc, argv, 0);
|
||||
}
|
||||
|
||||
struct rename_args {
|
||||
const char *src;
|
||||
const char *dst;
|
||||
};
|
||||
|
||||
static void *
|
||||
no_gvl_rename(void *ptr)
|
||||
{
|
||||
struct rename_args *ra = ptr;
|
||||
|
||||
return (void *)(VALUE)rename(ra->src, ra->dst);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* File.rename(old_name, new_name) -> 0
|
||||
|
@ -2886,19 +2899,20 @@ rb_file_s_unlink(int argc, VALUE *argv, VALUE klass)
|
|||
static VALUE
|
||||
rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
|
||||
{
|
||||
const char *src, *dst;
|
||||
struct rename_args ra;
|
||||
VALUE f, t;
|
||||
|
||||
FilePathValue(from);
|
||||
FilePathValue(to);
|
||||
f = rb_str_encode_ospath(from);
|
||||
t = rb_str_encode_ospath(to);
|
||||
src = StringValueCStr(f);
|
||||
dst = StringValueCStr(t);
|
||||
ra.src = StringValueCStr(f);
|
||||
ra.dst = StringValueCStr(t);
|
||||
#if defined __CYGWIN__
|
||||
errno = 0;
|
||||
#endif
|
||||
if (rename(src, dst) < 0) {
|
||||
if ((int)(VALUE)rb_thread_call_without_gvl(no_gvl_rename, &ra,
|
||||
RUBY_UBF_IO, 0) < 0) {
|
||||
int e = errno;
|
||||
#if defined DOSISH
|
||||
switch (e) {
|
||||
|
|
Loading…
Reference in a new issue