Permalink
Browse files

* 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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35800 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information...
1 parent 6d59771 commit fbf531c4a249e75260e80ed767114b02e0a1e985 @ko1 ko1 committed May 26, 2012
Showing with 72 additions and 88 deletions.
  1. +14 −0 ChangeLog
  2. +22 −0 benchmark/bm_vm3_backtrace.rb
  3. +36 −88 vm.c
View
@@ -1,3 +1,17 @@
+Sat May 26 12:18:09 2012 Koichi Sasada <ko1@atdot.net>
+
+ * 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@atdot.net>
* vm.c (rb_frame_info_t): keep previous ISEQ frame info for CFUNC
@@ -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
View
124 vm.c
@@ -851,6 +851,7 @@ frame_info_to_str(rb_frame_info_t *fi)
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 @@ bt_iter_cfunc(void *ptr, ID mid)
}
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 @@ backtrace_object(rb_thread_t *th, size_t lev, size_t n)
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 @@ rb_backtrace_to_str_ary(VALUE self)
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 @@ backtrace_load_data(VALUE self, VALUE str)
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 @@ oldbt_iter_cfunc(void *ptr, ID mid)
}
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;

0 comments on commit fbf531c

Please sign in to comment.