Skip to content

Instantly share code, notes, and snippets.

@lpm11
Last active December 13, 2015 17:09
Show Gist options
  • Save lpm11/4945388 to your computer and use it in GitHub Desktop.
Save lpm11/4945388 to your computer and use it in GitHub Desktop.
Just another Unscientific Benchmark of Topaz vs. MRI-Ruby.

Just Another Unscientific Benchmark of MRI vs. Topaz

Inspired by https://gist.github.com/havenwood/4724778.

Code

# for topaz
class String
  def _rjust(x,c=" ")
    return self if (self.length > x);
    return c*(x-self.length) + self;
  end

  def _ljust(x,c=" ")
    return self if (self.length > x);
    return self + c*(x-self.length);
  end
end

class Numeric
  def _floor(x)
    return (((self*(10**x)).to_i()).to_f())/((10**x).to_f());
  end
  
  def _p()
    return (self._floor(6).to_s())._ljust(8,"0")._rjust(9);
  end
end

$lcg_seed = 723;
def _srand(seed)
  $lcg_seed = seed;
end
def _rand()
  $lcg_seed = (($lcg_seed*1103515245)&2147483647)+12345;
  return $lcg_seed & 2147483647;
end

def benchmark(title, &block)
  a = [];
  
  5.times {
    t = Time.now;
    block.call;
    a << Time.now - t;
  }
  
  average = a.inject(0) { |s,x| s+x }/a.size.to_f();
  variance = a.inject(0) { |s,x| s+(x-average)**2 }/(a.size-1).to_f();
  df = 2.7764;
  mi = df * Math.sqrt(variance / (a.size-1));
  
  puts(title._rjust(15) + ": #{average._p}   #{(average-mi)._p} - #{(average+mi)._p}");
end

puts(" "*17 + "average"._rjust(9) + "   " + "95%-lwr"._rjust(9) + "   " + "95%-upr"._rjust(9));

# ensure timer works well
benchmark("sleep200ms") { sleep(0.2); }

# random
benchmark("lcgrand") {
  _srand(72300);
  10000000.times { _rand(); }
}
# 
# sort
_srand(723);
unsorted = (0...1000000).map { _rand(); };
benchmark("sort") {
  sorted = unsorted.sort();
}

# fib
def fib(n)
  return n<2 ? n:(fib(n-2)+fib(n-1));
end
benchmark("fibonacci") { fib(35); }

benchmark("eratosthen-ish") {
  a = (0..2500000).to_a();
  l = a.last;
  (a.first...a.last).each { |i|
    a[i] = nil if (i<2);
    next if (!a[i]);

    (i+i).step(l,i) { |x| a[x] = nil; }
  }
  # a.compact!();
}

# strcat
benchmark("strcat") {
  s = "";
  5000000.times { |i| s << "unko"; };
}

# gsub
benchmark("gsub") {
  s = "unko"*10000000;
  s.gsub("ko","nchi");
}

benchmark("regexp") {
  r = /http:\/\/[\-\.\/a-zA-Z0-9:\@&=+\$,%#]/;
  s = "unko"*100000 + "http://lpm11.net/" + "unko"*100000;
  1000.times { r =~ s; };
}

At-a-glance result

  • 10 faster: lcgrand, strcat

  • 5 faster: gsub

  • 2 faster: fibonacci, eratosthen-ish

  • slower: regexp, sort

Result

Note: Following time is result at rubbish machine, so result may varies (Sexy prime benchmark takes 309.95 sec at MRI, 19.09 sec at Topaz).

Topaz trunk

                   average     95%-lwr     95%-upr
     sleep200ms:  0.200383    0.200336 -  0.200430
        lcgrand:  0.137908    0.126807 -  0.149009
           sort:  5.499931    5.308957 -  5.690904
      fibonacci:  4.449075    3.482507 -  5.415642
 eratosthen-ish:  2.769728    2.198354 -  3.341102
         strcat:  0.529514    0.449336 -  0.609693
           gsub:  2.555540    2.464100 -  2.646981
         regexp:  2.461864    2.413191 -  2.510536

MRI (Ruby 1.9.3-p327)

                   average     95%-lwr     95%-upr
     sleep200ms:  0.200188    0.200113 -  0.200264
        lcgrand: 11.569965   11.316432 - 11.823498
           sort:  0.825600    0.731737 -  0.919462
      fibonacci: 10.994121    10.90808 - 11.080162
 eratosthen-ish:  6.989114    6.949861 -  7.028367
         strcat:  9.130288    9.066262 -  9.194313
           gsub: 12.623258    11.82916 - 13.417356
         regexp:  0.706247    0.681439 -  0.731056

Misc

  • Topaz currently not supports String#rjust, Numeric#floor ? :P
  • Crystal (https://github.com/manastech/crystal) may even faster, but seems to not support block argument, so didn't tried.
Syntax error in /home/lpm11/warabench.rb:36: expecting token 'IDENT', not '&'

def benchmark(title, &block)
@asterite
Copy link

Yes, Crystal doesn't support block arguments yet, but you can use "yield", no need to use the &block argument in your case.

But, anyway, Crystal still misses a lot of the functionality found in Ruby's std, like the Time class. But your benchmarks look very interesting, we'll try to make them work as soon as possible in Crystal and we'll let you know the times. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment