[前][次][番号順一覧][スレッド一覧]

ruby-changes:47972

From: normal <ko1@a...>
Date: Mon, 2 Oct 2017 06:19:29 +0900 (JST)
Subject: [ruby-changes:47972] normal:r60088 (trunk): File#rename releases GVL

normal	2017-10-02 06:19:24 +0900 (Mon, 02 Oct 2017)

  New Revision: 60088

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60088

  Log:
    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

  Added files:
    trunk/benchmark/bm_file_rename.rb
  Modified files:
    trunk/file.c
Index: benchmark/bm_file_rename.rb
===================================================================
--- benchmark/bm_file_rename.rb	(nonexistent)
+++ benchmark/bm_file_rename.rb	(revision 60088)
@@ -0,0 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/bm_file_rename.rb#L1
+# 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! }
Index: file.c
===================================================================
--- file.c	(revision 60087)
+++ file.c	(revision 60088)
@@ -2873,6 +2873,19 @@ rb_file_s_unlink(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/file.c#L2873
     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, https://github.com/ruby/ruby/blob/trunk/file.c#L2899
 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) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]