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

ruby-changes:37349

From: normal <ko1@a...>
Date: Thu, 29 Jan 2015 02:06:56 +0900 (JST)
Subject: [ruby-changes:37349] normal:r49430 (trunk): thread.c: micro-optimize thread create/join

normal	2015-01-29 02:06:40 +0900 (Thu, 29 Jan 2015)

  New Revision: 49430

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

  Log:
    thread.c: micro-optimize thread create/join
    
    * thread.c (struct join_arg): restructure and make smaller
      (thread_join_sleep): avoid timeofday() call if forever
      (thread_join): pass join_arg.delay directly
      (rb_thread_inspect_msg): remove, inline into rb_thread_inspect
      (rb_thread_inspect): reduce branching and string creation
    * thread_pthread.c (native_set_thread_name): create string directly
      to avoid reparsing. [Misc #10723]
    
    This reduces time in benchmark/bm_vm_thread_create_join.rb by
    a few percent.
    
    Minor improvements only:
    
    target 0: 2.1.5 (ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux])
    target 1: trunk (ruby 2.3.0dev (2015-01-16 trunk 49282) [x86_64-linux])
    target 2: built (ruby 2.3.0dev (2015-01-16 trunk 49282) [x86_64-linux])
    
    benchmark results:
    minimum results in each 3 measurements.
    Execution time (sec)
    name                    2.1.5   trunk   built
    vm_thread_create_join   1.049   1.242   1.138
    
    Speedup ratio: compare with the result of `2.1.5' (greater is better)
    name                    trunk   built
    vm_thread_create_join   0.845   0.923

  Modified files:
    trunk/ChangeLog
    trunk/thread.c
    trunk/thread_pthread.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 49429)
+++ ChangeLog	(revision 49430)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jan 29 02:06:09 2015  Eric Wong  <e@8...>
+
+	* thread.c (struct join_arg): restructure and make smaller
+	  (thread_join_sleep): avoid timeofday() call if forever
+	  (thread_join): pass join_arg.delay directly
+	  (rb_thread_inspect_msg): remove, inline into rb_thread_inspect
+	  (rb_thread_inspect): reduce branching and string creation
+	* thread_pthread.c (native_set_thread_name): create string directly
+	  to avoid reparsing. [Misc #10723]
+
 Wed Jan 28 21:32:24 2015  SHIBATA Hiroshi  <shibata.hiroshi@g...>
 
 	* thread.c: Improve documentation for Thread#value
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 49429)
+++ thread_pthread.c	(revision 49430)
@@ -1447,36 +1447,35 @@ timer_thread_sleep(rb_global_vm_lock_t* https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1447
 # define SET_THREAD_NAME(name) (void)0
 #endif
 
-static VALUE rb_thread_inspect_msg(VALUE thread, int show_enclosure, int show_location, int show_status);
-
 static void
 native_set_thread_name(rb_thread_t *th)
 {
 #if defined(__linux__) && defined(PR_SET_NAME)
-    VALUE str;
-    char *name, *p;
-    char buf[16];
-    size_t len;
+    if (!th->first_func && th->first_proc) {
+	VALUE loc = rb_proc_location(th->first_proc);
+	if (!NIL_P(loc)) {
+	    const VALUE *ptr = RARRAY_CONST_PTR(loc); /* [ String, Fixnum ] */
+	    char *name, *p;
+	    char buf[16];
+	    size_t len;
+	    int n;
 
-    str = rb_thread_inspect_msg(th->self, 0, 1, 0);
-    name = StringValueCStr(str);
-    if (*name == '@')
-        name++;
-    p = strrchr(name, '/'); /* show only the basename of the path. */
-    if (p && p[1])
-        name = p + 1;
+	    name = RSTRING_PTR(ptr[0]);
+	    p = strrchr(name, '/'); /* show only the basename of the path. */
+	    if (p && p[1])
+		name = p + 1;
 
-    len = strlen(name);
-    if (len < sizeof(buf)) {
-        memcpy(buf, name, len);
-        buf[len] = '\0';
-    }
-    else {
-        memcpy(buf, name, sizeof(buf)-2);
-        buf[sizeof(buf)-2] = '*';
-        buf[sizeof(buf)-1] = '\0';
+	    n = snprintf(buf, sizeof(buf), "%s:%d", name, NUM2INT(ptr[1]));
+	    rb_gc_force_recycle(loc); /* acts as a GC guard, too */
+
+	    len = (size_t)n;
+	    if (len >= sizeof(buf)) {
+		buf[sizeof(buf)-2] = '*';
+		buf[sizeof(buf)-1] = '\0';
+	    }
+	    SET_THREAD_NAME(buf);
+	}
     }
-    SET_THREAD_NAME(buf);
 #endif
 }
 
Index: thread.c
===================================================================
--- thread.c	(revision 49429)
+++ thread.c	(revision 49430)
@@ -796,8 +796,7 @@ rb_thread_create(VALUE (*fn)(ANYARGS), v https://github.com/ruby/ruby/blob/trunk/thread.c#L796
 
 struct join_arg {
     rb_thread_t *target, *waiting;
-    double limit;
-    int forever;
+    double delay;
 };
 
 static VALUE
@@ -826,14 +825,15 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L825
 {
     struct join_arg *p = (struct join_arg *)arg;
     rb_thread_t *target_th = p->target, *th = p->waiting;
-    double now, limit = p->limit;
+    const int forever = p->delay == DELAY_INFTY;
+    const double limit = forever ? 0 : timeofday() + p->delay;
 
     while (target_th->status != THREAD_KILLED) {
-	if (p->forever) {
+	if (forever) {
 	    sleep_forever(th, 1, 0);
 	}
 	else {
-	    now = timeofday();
+	    double now = timeofday();
 	    if (now > limit) {
 		thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
 			     thread_id_str(target_th));
@@ -862,8 +862,7 @@ thread_join(rb_thread_t *target_th, doub https://github.com/ruby/ruby/blob/trunk/thread.c#L862
 
     arg.target = target_th;
     arg.waiting = th;
-    arg.limit = timeofday() + delay;
-    arg.forever = delay == DELAY_INFTY;
+    arg.delay = delay;
 
     thread_debug("thread_join (thid: %"PRI_THREAD_ID")\n", thread_id_str(target_th));
 
@@ -2711,8 +2710,15 @@ rb_thread_safe_level(VALUE thread) https://github.com/ruby/ruby/blob/trunk/thread.c#L2710
     return INT2NUM(th->safe_level);
 }
 
+/*
+ * call-seq:
+ *   thr.inspect   -> string
+ *
+ * Dump the name, id, and status of _thr_ to a string.
+ */
+
 static VALUE
-rb_thread_inspect_msg(VALUE thread, int show_enclosure, int show_location, int show_status)
+rb_thread_inspect(VALUE thread)
 {
     VALUE cname = rb_class_path(rb_obj_class(thread));
     rb_thread_t *th;
@@ -2721,43 +2727,21 @@ rb_thread_inspect_msg(VALUE thread, int https://github.com/ruby/ruby/blob/trunk/thread.c#L2727
 
     GetThreadPtr(thread, th);
     status = thread_status_name(th);
-    if (show_enclosure)
-        str = rb_sprintf("#<%"PRIsVALUE":%p", cname, (void *)thread);
-    else
-        str = rb_str_new(NULL, 0);
-    if (show_location && !th->first_func && th->first_proc) {
-	long i;
-	VALUE v, loc = rb_proc_location(th->first_proc);
+    str = rb_sprintf("#<%"PRIsVALUE":%p", cname, (void *)thread);
+    if (!th->first_func && th->first_proc) {
+	VALUE loc = rb_proc_location(th->first_proc);
 	if (!NIL_P(loc)) {
-	    char sep = '@';
-	    for (i = 0; i < RARRAY_LEN(loc) && !NIL_P(v = RARRAY_AREF(loc, i)); ++i) {
-		rb_str_catf(str, "%c%"PRIsVALUE, sep, v);
-		sep = ':';
-	    }
+	    const VALUE *ptr = RARRAY_CONST_PTR(loc);
+	    rb_str_catf(str, "@%"PRIsVALUE":%"PRIsVALUE, ptr[0], ptr[1]);
+	    rb_gc_force_recycle(loc);
 	}
     }
-    if (show_status || show_enclosure)
-        rb_str_catf(str, " %s%s",
-                show_status ? status : "",
-                show_enclosure ? ">" : "");
+    rb_str_catf(str, " %s>", status);
     OBJ_INFECT(str, thread);
 
     return str;
 }
 
-/*
- * call-seq:
- *   thr.inspect   -> string
- *
- * Dump the name, id, and status of _thr_ to a string.
- */
-
-static VALUE
-rb_thread_inspect(VALUE thread)
-{
-    return rb_thread_inspect_msg(thread, 1, 1, 1);
-}
-
 /* variables for recursive traversals */
 static ID recursive_key;
 

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

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