diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-26 03:25:15 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-26 03:25:15 +0000 |
commit | fbf531c4a249e75260e80ed767114b02e0a1e985 (patch) | |
tree | e4d7d74812f89b89bff865595de72c3148552da9 | |
parent | 6d597718cf45aff0dd25ee7c7e8bd8e158ac0268 (diff) |
* 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
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | benchmark/bm_vm3_backtrace.rb | 22 | ||||
-rw-r--r-- | vm.c | 124 |
3 files changed, 72 insertions, 88 deletions
@@ -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 diff --git a/benchmark/bm_vm3_backtrace.rb b/benchmark/bm_vm3_backtrace.rb new file mode 100644 index 0000000000..0fbf73e1ca --- /dev/null +++ b/benchmark/bm_vm3_backtrace.rb @@ -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 @@ -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; |