Revert cbson.c, to be revisited for malloc/free reduction.
README.md has API Documentation note at the top to help users match documentation to driver version, DOCS-197. Expanded performance tests, for insert with multiple docs.
This commit is contained in:
parent
ca7bf209dd
commit
50d6902d80
2
Gemfile
2
Gemfile
@ -9,6 +9,8 @@ group :development, :test do
|
||||
|
||||
# Deployment
|
||||
gem "git"
|
||||
gem "redcarpet"
|
||||
gem "yard"
|
||||
|
||||
# Testing
|
||||
gem "mocha"
|
||||
|
23
README.md
23
README.md
@ -1,3 +1,17 @@
|
||||
# Documentation
|
||||
|
||||
This API documentation is available online at [http://api.mongodb.org/ruby](http://api.mongodb.org/ruby)
|
||||
for all releases of the MongoDB Ruby driver. Please reference the exact version of the documentation
|
||||
that matches the release of the Ruby driver that you are using. Note that the
|
||||
[Ruby Language Center for MongoDB](http://www.mongodb.org/display/DOCS/Ruby+Language+Center)
|
||||
has a link to API Documentation for the current release.
|
||||
|
||||
If you have the source, you can generate the matching documentation by typing
|
||||
|
||||
$ rake ydoc
|
||||
|
||||
Then open the file +ydoc/index.html+.
|
||||
|
||||
# Introduction
|
||||
|
||||
This is the 10gen-supported Ruby driver for [MongoDB](http://www.mongodb.org).
|
||||
@ -300,15 +314,6 @@ If you want to test replica set, you can run the following task:
|
||||
|
||||
$ rake test:rs
|
||||
|
||||
# Documentation
|
||||
|
||||
This documentation is available online at [http://api.mongodb.org/ruby](http://api.mongodb.org/ruby). You can
|
||||
generate the documentation if you have the source by typing
|
||||
|
||||
$ rake ydoc
|
||||
|
||||
Then open the file +ydoc/index.html+.
|
||||
|
||||
# Release Notes
|
||||
|
||||
See HISTORY.
|
||||
|
@ -18,13 +18,18 @@
|
||||
width:800px;
|
||||
height:400px;
|
||||
}
|
||||
div.hidden {
|
||||
//display: none; //visibility: hidden; // to collapse, use display: none
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Exp Series Performance Tests</h1>
|
||||
x-axis is power of 2, log base 2 of size<br>
|
||||
y-axis is operations per user-time CPU-second<br>
|
||||
Note that this is not operations per real-time second that include DB real-time<br>
|
||||
y-axis is "document" operations per second, ex., total document insertions per second<br>
|
||||
<br>
|
||||
For measuring Ruby driver performance, we are interested primarily in the "user" CPU time.<br>
|
||||
The "user" time is the time used by the Ruby driver, typically much less than real time.<br>
|
||||
<div id="placeholder"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -42,7 +47,7 @@
|
||||
return $.map(plotSpecs, function(plotSpec, i){
|
||||
return {
|
||||
label: labelSpec + ': ' + plotSpec[labelSpec],
|
||||
data: genOpXY(expSeries, xMax, plotSpec, 'exp2', 'ops'),
|
||||
data: genOpXY(expSeries, xMax, plotSpec, 'exp2', 'ut_ops'),
|
||||
lines: { show: true },
|
||||
points: { show: true }
|
||||
};
|
||||
@ -58,106 +63,108 @@ $(function () {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function doPlot(title, series) {
|
||||
function doPlot(title, series, classes) {
|
||||
var id = title.replace(/\W/g,'_');
|
||||
$("#placeholder").append('<h1>' + title + '</h1><div id="' + id + '" class="graph"></div>');
|
||||
$.plot($('#' + id),
|
||||
series,
|
||||
{
|
||||
xaxis: { ticks: xExpTicks },
|
||||
yaxes: [ { min: 0 } ],
|
||||
legend: { position: 'ne' },
|
||||
grid: { hoverable: true }
|
||||
$("#placeholder").append('<h3>' + title + '</h3><div id="show_hide_' + id + '" class="show_hide">Show/Hide</div><div id="' + id + '" class="graph"></div>');
|
||||
var e = $('#' + id);
|
||||
$.plot(e, series, {
|
||||
xaxis:{ ticks:xExpTicks },
|
||||
yaxes:[
|
||||
{ min:0 }
|
||||
],
|
||||
legend:{ position:'ne' },
|
||||
grid:{ hoverable:true }
|
||||
});
|
||||
e.addClass(classes);
|
||||
}
|
||||
|
||||
// comment pending
|
||||
var graph = [
|
||||
[ 'value_string_size insert C versus Ruby', 14, 'mode',
|
||||
[ '#placeholder', 'value_string_size insert C versus Ruby', 'hidden', 14, 'mode',
|
||||
[
|
||||
{ base:2, generator:'value_string_size', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'value_string_size', operation:'insert', mode: 'ruby', tag: 'orig_ruby' }
|
||||
{ base:2, generator:'value_string_size', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'value_string_size', operation:'insert', mode: 'ruby', tag: 'base_ruby' }
|
||||
]
|
||||
],
|
||||
[ 'key_string_size insert C versus Ruby', 14, 'mode',
|
||||
[ '#placeholder', 'key_string_size insert C versus Ruby', 'hidden', 14, 'mode',
|
||||
[
|
||||
{ base:2, generator:'key_string_size', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'key_string_size', operation:'insert', mode: 'ruby', tag: 'orig_ruby' }
|
||||
{ base:2, generator:'key_string_size', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'key_string_size', operation:'insert', mode: 'ruby', tag: 'base_ruby' }
|
||||
]
|
||||
],
|
||||
[ 'array_size_fixnum insert C versus Ruby', 12, 'mode',
|
||||
[ '#placeholder', 'array_size_fixnum insert C versus Ruby', 'hidden', 12, 'mode',
|
||||
[
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'ruby', tag: 'orig_ruby' }
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'ruby', tag: 'base_ruby' }
|
||||
]
|
||||
],
|
||||
[ 'hash_size_fixnum insert C versus Ruby', 12, 'mode',
|
||||
[ '#placeholder', 'hash_size_fixnum insert C versus Ruby', 'hidden', 12, 'mode',
|
||||
[
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'ruby', tag: 'orig_ruby' }
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'ruby', tag: 'base_ruby' }
|
||||
]
|
||||
],
|
||||
[ 'array_nest_fixnum base 2 insert C versus Ruby', 12, 'mode',
|
||||
[ '#placeholder', 'array_nest_fixnum base 2 insert C versus Ruby', 'hidden', 12, 'mode',
|
||||
[
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode:'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode:'ruby', tag: 'orig_ruby' }
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode:'c', tag: 'base_c' },
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode:'ruby', tag: 'base_ruby' }
|
||||
]
|
||||
],
|
||||
[ 'hash_nest_fixnum base 2 insert C versus Ruby', 12, 'mode',
|
||||
[ '#placeholder', 'hash_nest_fixnum base 2 insert C versus Ruby', 'hidden', 12, 'mode',
|
||||
[
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'ruby', tag: 'orig_ruby' }
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'ruby', tag: 'base_ruby' }
|
||||
]
|
||||
],
|
||||
[ 'array_nest_fixnum insert C by base', 12, 'base',
|
||||
[ '#placeholder', 'array_nest_fixnum insert C by base', 'hidden', 12, 'base',
|
||||
[
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:4, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:8, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:16, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:32, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' }
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:4, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:8, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:16, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:32, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' }
|
||||
]
|
||||
],
|
||||
[ 'hash_nest_fixnum insert C by base', 12, 'base',
|
||||
[ '#placeholder', 'hash_nest_fixnum insert C by base', 'hidden', 12, 'base',
|
||||
[
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:4, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:8, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:16, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:32, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' }
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:4, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:8, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:16, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' },
|
||||
{ base:32, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c_nest_full' }
|
||||
]
|
||||
],
|
||||
[ 'array_size_fixnum slow versus hash_size_fixnum insert C', 12, 'generator',
|
||||
[ '#placeholder', 'array_size_fixnum slow versus hash_size_fixnum insert C', '', 12, 'generator',
|
||||
[
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' }
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'c', tag: 'base_c' }
|
||||
]
|
||||
],
|
||||
[ 'array_size_fixnum slow versus fast insert C', 12, 'tag',
|
||||
[ '#placeholder', 'array_size_fixnum slow versus fast insert C', 'hidden', 12, 'tag',
|
||||
[
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'array_fast' }
|
||||
]
|
||||
],
|
||||
[ 'array_size_fixnum fast versus hash_size_fixnum insert C', 12, 'generator',
|
||||
[ '#placeholder', 'array_size_fixnum fast versus hash_size_fixnum insert C', 'hidden', 12, 'generator',
|
||||
[
|
||||
{ base:2, generator:'array_size_fixnum', operation:'insert', mode: 'c', tag: 'array_fast' },
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' }
|
||||
{ base:2, generator:'hash_size_fixnum', operation:'insert', mode: 'c', tag: 'base_c' }
|
||||
]
|
||||
],
|
||||
[ 'array_nest_fixnum slow versus hash_nest_fixnum insert C base 2', 12, 'generator',
|
||||
[ '#placeholder', 'array_nest_fixnum slow versus hash_nest_fixnum insert C base 2', 'hidden', 12, 'generator',
|
||||
[
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' }
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c' }
|
||||
]
|
||||
],
|
||||
[ 'array_nest_fixnum slow versus fast insert C base 2', 12, 'tag',
|
||||
[ '#placeholder', 'array_nest_fixnum slow versus fast insert C base 2', 'hidden', 12, 'tag',
|
||||
[
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_slow' },
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'base_c' },
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_fast' }
|
||||
]
|
||||
],
|
||||
[ 'array_nest_fixnum fast versus hash_nest_fixnum insert C base 2', 12, 'generator',
|
||||
[ '#placeholder', 'array_nest_fixnum fast versus hash_nest_fixnum insert C base 2', 'hidden', 12, 'generator',
|
||||
[
|
||||
{ base:2, generator:'array_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_fast' },
|
||||
{ base:2, generator:'hash_nest_fixnum', operation:'insert', mode: 'c', tag: 'array_fast' }
|
||||
@ -165,10 +172,11 @@ $(function () {
|
||||
],
|
||||
];
|
||||
$.each(graph, function(i, e){
|
||||
var title, xMax, labelSpec, plotSpecs;
|
||||
title = e[0]; xMax = e[1]; labelSpec = e[2]; plotSpecs = e[3]; //[title, xMax, labelSpec, plotSpecs] = e;
|
||||
var section, title, classes, xMax, labelSpec, plotSpecs;
|
||||
//[section, title, classes, xMax, labelSpec, plotSpecs] = e;
|
||||
section = e[0], title = e[1]; classes = e[2], xMax = e[3]; labelSpec = e[4]; plotSpecs = e[5];
|
||||
var series = flotSeries(expSeries, xMax, labelSpec, plotSpecs);
|
||||
doPlot(title, series);
|
||||
doPlot(title, series, classes);
|
||||
});
|
||||
|
||||
function showTooltip(x, y, contents) {
|
||||
@ -206,6 +214,11 @@ $(function () {
|
||||
}
|
||||
});
|
||||
|
||||
$('.show_hide').bind('click', function(event) {
|
||||
var id = $(this).attr('id').replace(/^show_hide_/, '');
|
||||
$('#' + id).toggleClass('hidden');
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
1130
bench/exp_series.js
1130
bench/exp_series.js
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,7 @@ $calibration_runtime = 0.1
|
||||
$target_runtime = 5.0
|
||||
$db_name = 'benchmark'
|
||||
$collection_name = 'exp_series'
|
||||
$mode = set_mode('ruby')
|
||||
$mode = set_mode('c')
|
||||
$hostname = `uname -n`[/([^.]*)/,1]
|
||||
$osname = `uname -s`.strip
|
||||
$tag = `git log -1 --format=oneline`.split[0]
|
||||
@ -34,7 +34,7 @@ $date = Time.now.strftime('%Y%m%d-%H%M')
|
||||
|
||||
options_with_help = [
|
||||
[ '--help', '-h', GetoptLong::NO_ARGUMENT, '', 'show help' ],
|
||||
[ '--mode', '-m', GetoptLong::OPTIONAL_ARGUMENT, ' mode', 'set mode to "c" or "ruby" (default)' ],
|
||||
[ '--mode', '-m', GetoptLong::OPTIONAL_ARGUMENT, ' mode', 'set mode to "c" or "ruby" (c)' ],
|
||||
[ '--tag', '-t', GetoptLong::OPTIONAL_ARGUMENT, ' tag', 'set tag for run, default is git commit key' ]
|
||||
]
|
||||
options = options_with_help.collect{|option|option[0...3]}
|
||||
@ -88,13 +88,6 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
return Array.new(base, array_nest(base, level - 1, obj))
|
||||
end
|
||||
|
||||
def hash_nest(base, level, obj)
|
||||
return obj if level == 0
|
||||
h = Hash.new
|
||||
(0...base).each{|i| h[i.to_s] = hash_nest(base, level - 1, obj)}
|
||||
return h
|
||||
end
|
||||
|
||||
def test__array_nest
|
||||
assert_equal(1, array_nest(2,0,1))
|
||||
assert_equal([1, 1], array_nest(2,1,1))
|
||||
@ -107,6 +100,13 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
assert_equal([1, 1, 1, 1, 1, 1, 1, 1], array_nest(8,1,1))
|
||||
end
|
||||
|
||||
def hash_nest(base, level, obj)
|
||||
return obj if level == 0
|
||||
h = Hash.new
|
||||
(0...base).each{|i| h[i.to_s] = hash_nest(base, level - 1, obj)}
|
||||
return h
|
||||
end
|
||||
|
||||
def test__hash_nest
|
||||
assert_equal(1, hash_nest(2, 0, 1))
|
||||
assert_equal({"0"=>1, "1"=>1}, hash_nest(2, 1, 1))
|
||||
@ -123,6 +123,25 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
assert_equal({"0"=>1, "1"=>1, "2"=>1, "3"=>1, "4"=>1, "5"=>1, "6"=>1, "7"=>1}, hash_nest(8,1,1))
|
||||
end
|
||||
|
||||
def multi_doc(multi_power, doc)
|
||||
return doc if multi_power == -1
|
||||
return (2 ** multi_power).times.collect{doc.dup}
|
||||
end
|
||||
|
||||
def test_multi_doc
|
||||
doc = {'a' => 1}
|
||||
assert_equal({"a"=>1}, multi_doc(-1, doc))
|
||||
assert_equal([{"a"=>1}], multi_doc(0, doc))
|
||||
assert_equal([{"a"=>1}, {"a"=>1}], multi_doc(1, doc))
|
||||
assert_equal([{"a"=>1}, {"a"=>1}, {"a"=>1}, {"a"=>1}], multi_doc(2, doc))
|
||||
assert_equal(8, multi_doc(3, doc).size)
|
||||
assert_equal(16, multi_doc(4, doc).size)
|
||||
assert_equal(32, multi_doc(5, doc).size)
|
||||
mdoc = multi_doc(2, doc)
|
||||
mdoc[0]['b'] = 2
|
||||
assert_equal([{"a"=>1, "b"=>2}, {"a"=>1}, {"a"=>1}, {"a"=>1}], mdoc, 'non-dup doc will fail for insert many safe')
|
||||
end
|
||||
|
||||
# Performance Tuning Engineering
|
||||
## Completed
|
||||
### How to measure and compare pure Ruby versus C extension performance
|
||||
@ -167,7 +186,7 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
# consider inserting the results into a database collection
|
||||
# Test::Unit::TestCase pollutes STDOUT, so write to a file
|
||||
File.open("exp_series-#{$date}-#{$tag}.js", 'w+'){|f|
|
||||
f.puts("#{@results.to_json.gsub(/\[/, "").gsub(/(}[\],])/, "},\n")}") unless @results.empty?
|
||||
f.puts(@results.to_json.gsub(/\[/, "").gsub(/}[\],]/, "},\n")) unless @results.empty?
|
||||
}
|
||||
@conn.drop_database($db_name)
|
||||
end
|
||||
@ -206,23 +225,34 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
return [iterations, utime, rtime, etime]
|
||||
end
|
||||
|
||||
def power_test(base, max_power, db, coll, generator, setup, operation, teardown)
|
||||
def power_test(args)
|
||||
base, max_power, multi, generator, setup, operation, teardown = args
|
||||
generator, setup, operation, teardown = method(generator), method(setup), method(operation), method(teardown)
|
||||
return (0..max_power).collect do |power|
|
||||
multi_start, multi_end = (multi == -1) ? [-1, -1] : [0, multi]
|
||||
(multi_start..multi_end).collect do |multi_power|
|
||||
size, doc = generator.call(base, power)
|
||||
iterations, utime, rtime, etime = valuate(db, coll, doc, setup, teardown) { operation.call(coll, doc) }
|
||||
doc = multi_doc(multi_power, doc)
|
||||
multi_size = (doc.class == Array) ? doc.size : 1;
|
||||
iterations, utime, rtime, etime = valuate(@db, @coll, doc, setup, teardown) { operation.call(@coll, doc) }
|
||||
multi_iterations = multi_size.to_f * iterations.to_f
|
||||
result = {
|
||||
'base' => base,
|
||||
'power' => power,
|
||||
'size' => size,
|
||||
'exp2' => Math.log2(size).to_i,
|
||||
'multi_power' => multi_power,
|
||||
'multi_size' => multi_size,
|
||||
'generator' => generator.name.to_s,
|
||||
'operation' => operation.name.to_s,
|
||||
'iterations' => iterations,
|
||||
'utime' => utime.round(2),
|
||||
'etime' => etime.round(2),
|
||||
'rtime' => rtime.round(2),
|
||||
'ops' => (iterations.to_f / utime.to_f).round(1),
|
||||
'usec' => (1000000.0 * utime.to_f / iterations.to_f).round(1),
|
||||
'ut_ops' => (multi_iterations / utime.to_f).round(1),
|
||||
'rt_ops' => (multi_iterations / rtime.to_f).round(1),
|
||||
'ut_usec' => (1000000.0 * utime.to_f / multi_iterations).round(1),
|
||||
'rt_usec' => (1000000.0 * rtime.to_f / multi_iterations).round(1),
|
||||
'etime' => etime.round(2),
|
||||
'mode' => $mode,
|
||||
'hostname' => $hostname,
|
||||
'osname' => $osname,
|
||||
@ -234,6 +264,7 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
STDERR.flush
|
||||
result
|
||||
end
|
||||
end.flatten
|
||||
end
|
||||
|
||||
def value_string_size(base, power)
|
||||
@ -277,19 +308,27 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def cursor_setup(db, coll, doc, iterations)
|
||||
(0...(iterations - coll.size)).each{insert(coll, doc)}
|
||||
(0...(iterations - coll.size)).each{insert(coll, doc)} #TODO - insert many
|
||||
@cursor = coll.find
|
||||
@queries = 1
|
||||
end
|
||||
|
||||
def clear_ids(doc) # delete :_id to really insert, required for safe
|
||||
if doc.class == Array
|
||||
doc.each{|d|d.delete(:_id)}
|
||||
else
|
||||
doc.delete(:_id)
|
||||
end
|
||||
end
|
||||
|
||||
def insert(coll, doc)
|
||||
doc.delete(:_id) # delete :_id to insert
|
||||
clear_ids(doc)
|
||||
coll.insert(doc) # note that insert stores :_id in doc and subsequent inserts are updates
|
||||
end
|
||||
|
||||
def insert_safe(coll, doc)
|
||||
doc.delete(:_id) # delete :_id to insert
|
||||
coll.insert(doc, :safe => true) # note that insert stores :_id in doc and subsequent inserts are updates
|
||||
clear_ids(doc)
|
||||
coll.insert(doc, :safe => true) # note that insert stores :_id in doc and subsequent inserts with :_id are updates
|
||||
end
|
||||
|
||||
def cursor_next(coll, doc)
|
||||
@ -317,123 +356,99 @@ class TestExpPerformance < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_insert
|
||||
tests = [
|
||||
[2, 15, :value_string_size, :null_setup, :insert, :default_teardown],
|
||||
[2, 15, :key_string_size, :null_setup, :insert, :default_teardown],
|
||||
[2, 14, :array_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 17, :hash_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 12, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[4, 6, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[8, 4, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[16, 3, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[32, 2, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 15, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[4, 8, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[8, 4, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[16, 4, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[32, 3, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
]
|
||||
tests.each do |base, max_power, generator, setup, operation, teardown|
|
||||
# consider moving 'method' as permitted by scope
|
||||
@results += power_test(base, max_power, @db, @coll, method(generator), method(setup), method(operation), method(teardown))
|
||||
[
|
||||
[2, 15, -1, :value_string_size, :null_setup, :insert, :default_teardown],
|
||||
[2, 15, -1, :key_string_size, :null_setup, :insert, :default_teardown],
|
||||
[2, 14, -1, :array_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 17, -1, :hash_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 12, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 15, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def test_insert_nest_full
|
||||
[
|
||||
[2, 12, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[4, 6, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[8, 4, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[16, 3, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[32, 2, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 15, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[4, 8, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[8, 4, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[16, 4, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[32, 3, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def test_array_fast
|
||||
[
|
||||
[2, 14, -1, :array_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 17, -1, :hash_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 12, -1, :array_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 15, -1, :hash_nest_fixnum, :null_setup, :insert, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def test_insert_safe
|
||||
tests = [
|
||||
[2, 15, :value_string_size, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 15, :key_string_size, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 14, :array_size_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 17, :hash_size_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 12, :array_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[4, 6, :array_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[8, 4, :array_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[16, 3, :array_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[32, 2, :array_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 15, :hash_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[4, 8, :hash_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[8, 4, :hash_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[16, 4, :hash_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[32, 3, :hash_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
]
|
||||
tests.each do |base, max_power, generator, setup, operation, teardown|
|
||||
# consider moving 'method' as permitted by scope
|
||||
@results += power_test(base, max_power, @db, @coll, method(generator), method(setup), method(operation), method(teardown))
|
||||
end
|
||||
[
|
||||
[2, 15, -1, :value_string_size, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 15, -1, :key_string_size, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 14, -1, :array_size_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 17, -1, :hash_size_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 12, -1, :array_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 15, -1, :hash_nest_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def xtest_insert_many
|
||||
|
||||
def test_insert_many
|
||||
[
|
||||
[2, 2, 10, :value_string_size, :null_setup, :insert, :default_teardown],
|
||||
[2, 14, 10, :hash_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
[2, 14, 10, :array_size_fixnum, :null_setup, :insert, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def xtest_insert_many_safe
|
||||
|
||||
def test_insert_many_safe
|
||||
[
|
||||
[2, 2, 10, :value_string_size, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 14, 10, :hash_size_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
[2, 14, 10, :array_size_fixnum, :null_setup, :insert_safe, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def test_find
|
||||
tests = [
|
||||
[2, 15, :value_string_size, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 15, :key_string_size, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 14, :array_size_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 17, :hash_size_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 12, :array_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[4, 6, :array_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[8, 4, :array_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[16, 3, :array_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[32, 2, :array_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 15, :hash_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[4, 8, :hash_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[8, 4, :hash_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[16, 4, :hash_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[32, 3, :hash_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
]
|
||||
tests.each do |base, max_power, generator, setup, operation, teardown|
|
||||
# consider moving 'method' as permitted by scope
|
||||
@results += power_test(base, max_power, @db, @coll, method(generator), method(setup), method(operation), method(teardown))
|
||||
end
|
||||
[
|
||||
[2, 15, -1, :value_string_size, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 15, -1, :key_string_size, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 14, -1, :array_size_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 17, -1, :hash_size_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 12, -1, :array_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
[2, 15, -1, :hash_nest_fixnum, :cursor_setup, :cursor_next, :cursor_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def test_find_one
|
||||
tests = [
|
||||
[2, 15, :value_string_size, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 15, :key_string_size, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 14, :array_size_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 17, :hash_size_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 12, :array_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[4, 6, :array_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[8, 4, :array_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[16, 3, :array_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[32, 2, :array_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 15, :hash_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[4, 8, :hash_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[8, 4, :hash_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[16, 4, :hash_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[32, 3, :hash_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
]
|
||||
tests.each do |base, max_power, generator, setup, operation, teardown|
|
||||
# consider moving 'method' as permitted by scope
|
||||
@results += power_test(base, max_power, @db, @coll, method(generator), method(setup), method(operation), method(teardown))
|
||||
end
|
||||
[
|
||||
[2, 15, -1, :value_string_size, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 15, -1, :key_string_size, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 14, -1, :array_size_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 17, -1, :hash_size_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 12, -1, :array_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
[2, 15, -1, :hash_nest_fixnum, :find_one_setup, :find_one, :default_teardown],
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def xtest_update
|
||||
tests = [
|
||||
[
|
||||
# pending
|
||||
]
|
||||
tests.each do |base, max_power, generator, setup, operation, teardown|
|
||||
# consider moving 'method' as permitted by scope
|
||||
@results += power_test(base, max_power, @db, @coll, method(generator), method(setup), method(operation), method(teardown))
|
||||
end
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
def xtest_remove
|
||||
tests = [
|
||||
[
|
||||
# pending
|
||||
]
|
||||
tests.each do |base, max_power, generator, setup, operation, teardown|
|
||||
# consider moving 'method' as permitted by scope
|
||||
@results += power_test(base, max_power, @db, @coll, method(generator), method(setup), method(operation), method(teardown))
|
||||
end
|
||||
].each{|args| @results += power_test(args)}
|
||||
end
|
||||
|
||||
# synthesized mix, real-world data pending
|
||||
|
@ -139,14 +139,38 @@ static void write_utf8(bson_buffer_t buffer, VALUE string, char check_null) {
|
||||
#define EXTENDED RE_OPTION_EXTENDED
|
||||
#endif
|
||||
|
||||
#define ARRAY_KEY_BUFFER_SIZE 10
|
||||
// use 8^(ARRAY_KEY_BUFFER_SIZE-1) as CPP safe bounds approximation for limit of 10^(ARRAY_KEY_BUFFER_SIZE-1)-1
|
||||
#define ARRAY_KEY_MAX_CPP (1 << (3 * (ARRAY_KEY_BUFFER_SIZE-1)))
|
||||
|
||||
/* TODO we ought to check that the malloc or asprintf was successful
|
||||
* and raise an exception if not. */
|
||||
/* TODO maybe we can use something more portable like vsnprintf instead
|
||||
* of this hack. And share it with the Python extension ;) */
|
||||
/* If we don't have ASPRINTF, there are two possibilities:
|
||||
* either use _scprintf and _snprintf on for Windows or
|
||||
* use snprintf for solaris. */
|
||||
#ifndef HAVE_ASPRINTF
|
||||
#ifdef _WIN32 || _MSC_VER
|
||||
#define SNPRINTF _snprintf
|
||||
#define INT2STRING(buffer, i) \
|
||||
{ \
|
||||
int vslength = _scprintf("%d", i) + 1; \
|
||||
*buffer = malloc(vslength); \
|
||||
_snprintf(*buffer, vslength, "%d", i); \
|
||||
}
|
||||
#define FREE_INTSTRING(buffer) free(buffer)
|
||||
#else
|
||||
#define SNPRINTF snprintf
|
||||
#define INT2STRING(buffer, i) \
|
||||
{ \
|
||||
int vslength = snprintf(NULL, 0, "%d", i) + 1; \
|
||||
*buffer = malloc(vslength); \
|
||||
snprintf(*buffer, vslength, "%d", i); \
|
||||
}
|
||||
#define FREE_INTSTRING(buffer) free(buffer)
|
||||
#endif
|
||||
#else
|
||||
#define INT2STRING(buffer, i) asprintf(buffer, "%d", i);
|
||||
#ifdef USING_SYSTEM_ALLOCATOR_LIBRARY /* Ruby Enterprise Edition with tcmalloc */
|
||||
#define FREE_INTSTRING(buffer) system_free(buffer)
|
||||
#else
|
||||
#define FREE_INTSTRING(buffer) free(buffer)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef RREGEXP_SRC
|
||||
@ -277,7 +301,6 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
||||
bson_buffer_position length_location, start_position, obj_length;
|
||||
int items, i;
|
||||
VALUE* values;
|
||||
char name[ARRAY_KEY_BUFFER_SIZE];
|
||||
|
||||
write_name_and_type(buffer, key, 0x04);
|
||||
start_position = bson_buffer_get_position(buffer);
|
||||
@ -289,14 +312,15 @@ static int write_element(VALUE key, VALUE value, VALUE extra, int allow_id) {
|
||||
}
|
||||
|
||||
items = RARRAY_LENINT(value);
|
||||
if (items > ARRAY_KEY_MAX_CPP)
|
||||
rb_raise(rb_eTypeError, "array size too large");
|
||||
for(i = 0; i < items; i++) {
|
||||
char* name;
|
||||
VALUE key;
|
||||
SNPRINTF(name, ARRAY_KEY_BUFFER_SIZE, "%d", i);
|
||||
INT2STRING(&name, i);
|
||||
key = rb_str_new2(name);
|
||||
write_element_with_id(key, rb_ary_entry(value, i), pack_extra(buffer, check_keys));
|
||||
FREE_INTSTRING(name);
|
||||
}
|
||||
|
||||
// write null byte and fill in length
|
||||
SAFE_WRITE(buffer, &zero, 1);
|
||||
obj_length = bson_buffer_get_position(buffer) - start_position;
|
||||
|
Loading…
Reference in New Issue
Block a user