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

ruby-changes:23749

From: ko1 <ko1@a...>
Date: Sat, 26 May 2012 12:25:26 +0900 (JST)
Subject: [ruby-changes:23749] ko1:r35800 (trunk): * vm.c (frame_info_to_str): add `break'.

ko1	2012-05-26 12:25:15 +0900 (Sat, 26 May 2012)

  New Revision: 35800

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

  Log:
    * vm.c (frame_info_to_str): add `break'.
    * vm.c (backtrace_object): remove lev and n parameter.
      backtrace_object always returns all of backtrace information.
    * vm.c (rb_backtrace_to_str_ary): fix to use backtrace_object().
      This change improve performance of caller(lev, n).
    * benchmark/bm_vm3_backtrace.rb: added to check above improvement.
      FYI: measurement on my laptop, 1.9.3p229 needs 5.125 sec,
      and current trunk only needs 0.299sec.

  Added files:
    trunk/benchmark/bm_vm3_backtrace.rb
  Modified files:
    trunk/ChangeLog
    trunk/vm.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 35799)
+++ ChangeLog	(revision 35800)
@@ -1,3 +1,17 @@
+Sat May 26 12:18:09 2012  Koichi Sasada  <ko1@a...>
+
+	* vm.c (frame_info_to_str): add `break'.
+
+	* vm.c (backtrace_object): remove lev and n parameter.
+	  backtrace_object always returns all of backtrace information.
+
+	* vm.c (rb_backtrace_to_str_ary): fix to use backtrace_object().
+	  This change improve performance of caller(lev, n).
+
+	* benchmark/bm_vm3_backtrace.rb: added to check above improvement.
+	  FYI: measurement on my laptop, 1.9.3p229 needs 5.125 sec, 
+	  and current trunk only needs 0.299sec.
+
 Sat May 26 11:05:09 2012  Koichi Sasada  <ko1@a...>
 
 	* vm.c (rb_frame_info_t): keep previous ISEQ frame info for CFUNC
Index: vm.c
===================================================================
--- vm.c	(revision 35799)
+++ vm.c	(revision 35800)
@@ -851,6 +851,7 @@
 	file = fi->body.iseq.iseq->location.filename;
 	line_no = fi->body.iseq.line_no.line_no;
 	name = fi->body.iseq.iseq->location.name;
+	break;
       case FRAME_INFO_TYPE_CFUNC:
 	if (fi->body.cfunc.prev_fi) {
 	    file = fi->body.cfunc.prev_fi->body.iseq.iseq->location.filename;
@@ -1022,7 +1023,7 @@
 }
 
 static VALUE
-backtrace_object(rb_thread_t *th, size_t lev, size_t n)
+backtrace_object(rb_thread_t *th)
 {
     struct bt_iter_arg arg;
     arg.prev_fi = 0;
@@ -1033,45 +1034,26 @@
 		   bt_iter_cfunc,
 		   &arg);
 
-    if (lev > 0) {
-	if (lev > arg.bt->backtrace_size) {
-	    arg.bt->backtrace = 0;
-	    arg.bt->backtrace_size = 0;
-	    arg.btobj = Qnil;
-	}
-	else {
-	    arg.bt->backtrace += lev;
-	    arg.bt->backtrace_size -= lev;
-	}
-    }
-
-    if (n > 0) {
-	if (n < arg.bt->backtrace_size) {
-	    arg.bt->backtrace_size = n; /* trim */
-	}
-    }
-
     return arg.btobj;
 }
 
 VALUE
 rb_vm_backtrace_object(void)
 {
-    return backtrace_object(GET_THREAD(), 0, 0);
+    return backtrace_object(GET_THREAD());
 }
 
 static VALUE
-backtreace_collect(rb_backtrace_t *bt, VALUE (*func)(rb_frame_info_t *))
+backtreace_collect(rb_backtrace_t *bt, int lev, int n, VALUE (*func)(rb_frame_info_t *))
 {
     VALUE btary;
-    size_t i;
+    int i;
 
-    btary = rb_ary_new2(bt->backtrace_size);
-    rb_ary_store(btary, bt->backtrace_size-1, Qnil); /* create places */
+    btary = rb_ary_new();
 
-    for (i=0; i<bt->backtrace_size; i++) {
-	rb_frame_info_t *fi = &bt->backtrace[i];
-	RARRAY_PTR(btary)[bt->backtrace_size - i - 1] = func(fi);
+    for (i=0; i+lev<(int)bt->backtrace_size && i<n; i++) {
+	rb_frame_info_t *fi = &bt->backtrace[bt->backtrace_size - 1 - (lev+i)];
+	rb_ary_push(btary, func(fi));
     }
 
     return btary;
@@ -1087,11 +1069,31 @@
 	return bt->strary;
     }
     else {
-	bt->strary = backtreace_collect(bt, frame_info_to_str);
+	bt->strary = backtreace_collect(bt, 0, bt->backtrace_size, frame_info_to_str);
 	return bt->strary;
     }
 }
 
+static VALUE
+backtrace_to_str_ary2(VALUE self, size_t lev, size_t n)
+{
+    rb_backtrace_t *bt;
+    size_t size;
+    GetCoreDataFromValue(self, rb_backtrace_t, bt);
+    /* fprintf(stderr, "btsize: %d, lev: %d, n: %d\n", (int)bt->backtrace_size, lev, n); */
+
+    size = bt->backtrace_size;
+
+    if (n == 0) {
+	n = size;
+    }
+    if (lev > size) {
+	return Qnil;
+    }
+
+    return backtreace_collect(bt, lev, n, frame_info_to_str);
+}
+
 #if 0
 static VALUE
 rb_backtrace_to_frame_ary(VALUE self)
@@ -1122,6 +1124,12 @@
     return self;
 }
 
+static VALUE
+vm_backtrace_str_ary(rb_thread_t *th, size_t lev, size_t n)
+{
+    return backtrace_to_str_ary2(backtrace_object(th), lev, n);
+}
+
 /* old style backtrace directly */
 
 struct oldbt_arg {
@@ -1164,66 +1172,6 @@
 }
 
 static void
-oldbt_push(void *data, VALUE file, int line_no, VALUE name)
-{
-    VALUE ary = (VALUE)data;
-    VALUE bt;
-
-    if (line_no) {
-	bt = rb_enc_sprintf(rb_enc_compatible(file, name), "%s:%d:in `%s'",
-			    RSTRING_PTR(file), line_no, RSTRING_PTR(name));
-    }
-    else {
-	bt = rb_enc_sprintf(rb_enc_compatible(file, name), "%s:in `%s'",
-			    RSTRING_PTR(file), RSTRING_PTR(name));
-    }
-    rb_ary_push(ary, bt);
-}
-
-static VALUE
-vm_backtrace_str_ary(rb_thread_t *th, size_t lev, size_t n)
-{
-    struct oldbt_arg arg;
-    VALUE ary, result;
-    int i;
-    size_t size;
-    VALUE *ptr;
-
-    arg.func = oldbt_push;
-    arg.data = (void *)rb_ary_new();
-
-    backtrace_each(th,
-		   oldbt_init,
-		   oldbt_iter_iseq,
-		   oldbt_iter_cfunc,
-		   &arg);
-
-    ary = (VALUE)arg.data;
-    size = RARRAY_LEN(ary);
-
-    /* ["top", "2nd", ..........., "size-th"] */
-    /*                 <-- n --> <-- lev -->  */
-    /*         return: [.......]              */
-
-    if (n == 0) {
-	n = size;
-    }
-
-    if (size < lev) {
-	return Qnil;
-    }
-
-    result = rb_ary_new();
-    ptr = RARRAY_PTR(ary);
-
-    for (i=0; i<(int)(size - lev) && i<(int)n; i++) {
-	rb_ary_push(result, ptr[(size - 1) - lev - i]);
-    }
-
-    return result;
-}
-
-static void
 oldbt_print(void *data, VALUE file, int line_no, VALUE name)
 {
     FILE *fp = (FILE *)data;
Index: benchmark/bm_vm3_backtrace.rb
===================================================================
--- benchmark/bm_vm3_backtrace.rb	(revision 0)
+++ benchmark/bm_vm3_backtrace.rb	(revision 35800)
@@ -0,0 +1,22 @@
+# get last backtrace
+
+begin
+  caller(0, 0)
+rescue ArgumentError
+  alias caller_orig caller
+  def caller lev, n
+    caller_orig(lev)[0..n]
+  end
+end
+
+def rec n
+  if n < 0
+    100_000.times{
+      caller(0, 1)
+    }
+  else
+    rec(n-1)
+  end
+end
+
+rec 50

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

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