Skip to content

Instantly share code, notes, and snippets.

@nagachika
Created November 5, 2011 14:01
Show Gist options
  • Save nagachika/1341532 to your computer and use it in GitHub Desktop.
Save nagachika/1341532 to your computer and use it in GitHub Desktop.
CRuby extension for stacksize.
require "benchmark"
require_relative "stacksize"
class EnumBlkCall
def initialize(num)
@num = num
end
def each(&blk)
i = 0
while i < @num
blk.call
i += 1
end
end
end
class EnumBlkYield
def initialize(num)
@num = num
end
def each
i = 0
while i < @num
yield
i += 1
end
end
end
puts "------------------------------------------------------"
Benchmark.benchmark("invoke block\n", 16) do |x|
a = Array.new(10000000){|i| i}
rslt = []
rslt << x.report("Proc#call:") { EnumBlkCall.new(10000000).each{ } }
rslt << x.report("yield :") { EnumBlkYield.new(10000000).each{ } }
sum = rslt.inject do |s, i| s + i end
[sum, sum / rslt.size]
end
def nested_each(arys)
a, *rest = arys
if a.nil?
GC.start if $run_gc
return nil
end
a.each do |i|
nested_each(rest)
end
nil
end
puts
puts "------------------------------------------------------"
Benchmark.benchmark("Deeply nested blocks\n", 16) do |x|
rslt = []
a = Array.new(1000){ EnumBlkCall.new(1) }
rslt << x.report("Proc#call :") { nested_each(a) }
a = Array.new(1000){ EnumBlkYield.new(1) }
rslt << x.report("yield :") { nested_each(a) }
sum = rslt.inject do |s, i| s + i end
[sum, sum / rslt.size]
end
puts
puts "------------------------------------------------------"
$run_gc = true
Benchmark.benchmark("Deeply nested blocks with GC\n", 16) do |x|
rslt = []
a = Array.new(1000){ EnumBlkCall.new(1) }
rslt << x.report("Proc#call :") { nested_each(a) }
a = Array.new(1000){ EnumBlkYield.new(1) }
rslt << x.report("yield :") { nested_each(a) }
sum = rslt.inject do |s, i| s + i end
[sum, sum / rslt.size]
end
require "mkmf"
srcdir = "/Users/nagachika/opt/ruby-trunk/src/ruby"
builddir = "/Users/nagachika/opt/ruby-trunk/src/build"
dir_config("ruby-src", srcdir, srcdir)
dir_config("ruby-build", builddir, builddir)
create_makefile("stacksize")
#include <ruby/ruby.h>
#include <vm_core.h>
VALUE
rb_thread_stack_length(VALUE klass)
{
VALUE thval;
rb_thread_t *th;
ptrdiff_t len;
thval = rb_funcall(rb_cThread, rb_intern("current"), 0);
th = RTYPEDDATA_DATA(thval);
len = th->cfp->sp - th->stack;
return LONG2NUM((long)len * sizeof(VALUE));
}
VALUE
rb_thread_frame_stack_length(VALUE klass)
{
VALUE thval;
rb_thread_t *th;
VALUE *bottom, *sp;
ptrdiff_t len;
thval = rb_funcall(rb_cThread, rb_intern("current"), 0);
th = RTYPEDDATA_DATA(thval);
bottom = (VALUE *)(th->stack + th->stack_size);
sp = (VALUE *)th->cfp;
len = (bottom - sp)*sizeof(VALUE);
return LONG2NUM((long)len);
}
VALUE
rb_thread_machine_stack_length(VALUE klass)
{
size_t len = ruby_stack_length(NULL);
return LONG2NUM((long)(len * sizeof(VALUE)));
}
void
Init_stacksize(void)
{
rb_define_singleton_method(rb_cThread, "stack_length", rb_thread_stack_length, 0);
rb_define_singleton_method(rb_cThread, "frame_stack_length", rb_thread_frame_stack_length, 0);
rb_define_singleton_method(rb_cThread, "machine_stack_length", rb_thread_machine_stack_length, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment