1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
#!/usr/local/bin/ruby -w
begin require 'rubygems' rescue LoadError end
require 'inline'
class MyTest
def factorial(n)
f = 1
n.downto(2) { |x| f *= x }
f
end
inline do |builder|
builder.c "
long factorial_c(int max) {
int i=max, result=1;
while (i >= 2) { result *= i--; }
return result;
}"
builder.c_raw "
static
VALUE
factorial_c_raw(int argc, VALUE *argv, VALUE self) {
int i=FIX2INT(argv[0]), result=1;
while (i >= 2) { result *= i--; }
return INT2NUM(result);
}"
end
end
t = MyTest.new()
arg = ARGV.shift || 0
arg = arg.to_i
# breakeven for build run vs native doing 5 factorial:
# on a PIII/750 running FreeBSD: about 5000
# on a PPC/G4/800 running Mac OSX 10.2: always faster
max = ARGV.shift || 1000000
max = max.to_i
puts "RubyInline #{Inline::VERSION}" if $DEBUG
MyTest.send(:alias_method, :factorial_alias, :factorial_c_raw)
def validate(n)
if n != 120 then puts "ACK! - #{n}"; end
end
tstart = Time.now
case arg
when 0 then
type = "Inline C "
(1..max).each { |m| n = t.factorial_c(5); validate(n); }
when 1 then
type = "InlineRaw"
(1..max).each { |m| n = t.factorial_c_raw(5); validate(n); }
when 2 then
type = "Alias "
(1..max).each { |m| n = t.factorial_alias(5); validate(n); }
when 3 then
type = "Native "
(1..max).each { |m| n = t.factorial(5); validate(n); }
else
$stderr.puts "ERROR: argument #{arg} not recognized"
exit(1)
end
tend = Time.now
total = tend - tstart
avg = total / max
printf "Type = #{type}, Iter = #{max}, T = %.8f sec, %.8f sec / iter\n", total, avg
|