1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00
therubyracer/benchmarks.rb
Charles Lowell 77804fce1c Don't check for strings and primitives in idmap.
It appears that `Ref::WeakValueMap` is not 100%
correct. There are cases where entries are 
temporarily corrupted; probably while attached
finalizers run.

This is a slight decrease in flexibility in that
strings and primitives cannot maintain referential
integrity when passed by reference to v8, but the
default is to pass them by value anyway, and it
greatly reduces the number of object_ids that the
idmap sees and therefore reduces the chances of 
a recycled object id causing a bad lookup.

While this is not a perfect fix, it does make a
collision very unlikely, and it prevents the 
crashes being seen in #169 

If this pops up again,
we'll have to look at getting a perfectly reliable
weakmap implementation.
2012-06-20 15:30:34 -05:00

217 lines
No EOL
4.6 KiB
Ruby

require 'bundler/setup'
require 'v8'
require 'benchmark'
require 'optparse'
OPTIONS = {
:times => 5,
:mode => :object,
:objects => 500
}
parser = OptionParser.new do |opts|
opts.on("-t", "--times [T]", Integer, "run benchmark N times") do |t|
OPTIONS[:times] = t
end
opts.on("-m", "--mode [MODE]", [:object, :function, :eval], "select the type of object access to stress test") do |mode|
mode = mode.to_sym
raise "unsupported mode #{mode}" unless [:object,:function,:eval].include?(mode)
OPTIONS[:mode] = mode
end
opts.on("-o", "--objects [N]", Integer, "create N objects for each iteration") do |n|
OPTIONS[:objects] = n
end
opts
end
parser.parse! ARGV
MODE = OPTIONS[:mode]
TIMES = OPTIONS[:times]
OBJECTS = OPTIONS[:objects]
puts "using #{OPTIONS[:mode]}"
if MODE==:object
def get(i)
@cxt["test"]["objects"][i]
end
elsif MODE==:function
def get(i)
@cxt["test"].getObject(i)
end
elsif MODE==:eval
def get(i)
@cxt.eval "test.getObject(#{i})"
end
end
js= <<JS
function createTest()
{
var test = {};
test.objects = [];
test.seed = 49734321;
test.summ;
test.random = function()
{
// Robert Jenkins' 32 bit integer hash function.
test.seed = ((test.seed + 0x7ed55d16) + (test.seed << 12)) & 0xffffffff;
test.seed = ((test.seed ^ 0xc761c23c) ^ (test.seed >>> 19)) & 0xffffffff;
test.seed = ((test.seed + 0x165667b1) + (test.seed << 5)) & 0xffffffff;
test.seed = ((test.seed + 0xd3a2646c) ^ (test.seed << 9)) & 0xffffffff;
test.seed = ((test.seed + 0xfd7046c5) + (test.seed << 3)) & 0xffffffff;
test.seed = ((test.seed ^ 0xb55a4f09) ^ (test.seed >>> 16)) & 0xffffffff;
return (test.seed & 0xfffffff) / 0x10000000;
};
test.init = function()
{
test.objects = [];
for(var i=0; i<#{OBJECTS}; i++)
{
var hash = {};
for(var j=0; j<10; j++)
{
var isString = test.random();
var key = "str" + test.random();
var value;
if(isString < 0.5)
value = "str" + test.random();
else
value = test.random();
hash[key] = value;
}
test.objects[i] = hash;
}
return test.objects.length;
}
test.findSum = function()
{
test.summ = 0;
var length = test.objects.length;
for(var i=0; i<length; i++)
{
var hash = test.objects[i];
for (var k in hash)
{
if (hash.hasOwnProperty(k) && (typeof(hash[k]) == "number"))
{
test.summ += hash[k];
}
}
}
return test.summ;
};
test.finalCheck = function()
{
var summ = 0;
var length = test.objects.length;
for(var i=0; i<length; i++)
{
var hash = test.objects[i];
for (var k in hash)
{
if (hash.hasOwnProperty(k) && (typeof(hash[k]) == "number"))
{
summ += hash[k];
}
}
}
return summ ;
};
test.getObject = function(index)
{
if(!test.objects[index]) return {};
return test.objects[index];
}
test.setObject = function(index, object)
{
test.objects[index] = object;
}
return test;
}
JS
def profile
Benchmark.realtime do
yield
end
end
def get_res result
result.to_f
end
puts "init js context..."
cxt = V8::Context.new
@cxt=cxt
cxt.eval(js)
cxt.eval('var test = createTest()')
puts "run init test"
result =profile do
TIMES.times do
cxt['test'].init()
end
end
puts "init time: #{get_res(result) / TIMES} sec."
sum1=sum2=0
puts "run findSum test"
result =profile do
TIMES.times do
sum1= cxt['test'].findSum
end
end
puts "findSum time: #{get_res(result) / TIMES} sec."
puts "run Objects inversion in ruby test"
result =profile do
TIMES.times do |j|
puts j
for i in 0..(OBJECTS-1) do
obj = get(i)
obj.each do |key, value|
if value.instance_of? Float
obj[key] = value * (-1)
end
end
end
end
end
puts "Objects time: #{get_res(result) / TIMES} sec."
puts "run finalCheck test"
result =profile do
TIMES.times do
sum2= cxt['test'].findSum
end
end
puts "final check time: #{get_res(result) / TIMES} sec."
puts "#{sum1==sum2*(TIMES%2==0?1:-1) ? 'TEST PASS': 'TEST FAIL'}: Sum before inversions: #{sum1} / Sum after inversions: #{sum2}"