diff options
author | John Christopher Anderson <jchris@apache.org> | 2009-10-16 21:38:11 +0000 |
---|---|---|
committer | John Christopher Anderson <jchris@apache.org> | 2009-10-16 21:38:11 +0000 |
commit | 2df3fabfdc2039504295219c88e0d160f76c1afb (patch) | |
tree | bf6784d510c7e0fec2705a490dce3933e81ddcbd /bench | |
parent | 51230872ffbedfcfcbc99ccc44d166f79307c7f0 (diff) |
added bench/ directory to trunk, contains 2 benchmark suites.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@826097 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'bench')
-rw-r--r-- | bench/Makefile.am | 16 | ||||
-rw-r--r-- | bench/bench_lib.js | 241 | ||||
-rwxr-xr-x | bench/benchbulk.sh | 69 | ||||
-rw-r--r-- | bench/benches.js | 62 | ||||
-rw-r--r-- | bench/out.file | 1 | ||||
-rwxr-xr-x | bench/runner.sh | 18 |
6 files changed, 407 insertions, 0 deletions
diff --git a/bench/Makefile.am b/bench/Makefile.am new file mode 100644 index 00000000..c98f4e01 --- /dev/null +++ b/bench/Makefile.am @@ -0,0 +1,16 @@ +## Licensed under the Apache License, Version 2.0 (the "License"); you may not +## use this file except in compliance with the License. You may obtain a copy of +## the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +## License for the specific language governing permissions and limitations under +## the License. + +EXTRA_DIST = \ + bench_lib.js \ + runner.sh \ + benches.js diff --git a/bench/bench_lib.js b/bench/bench_lib.js new file mode 100644 index 00000000..be7abcd9 --- /dev/null +++ b/bench/bench_lib.js @@ -0,0 +1,241 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// some monkeypatches +var JSON = { + parse : function(string) { + return eval('('+string+')'); + }, + stringify : function(obj) { + return toJSON(obj||null); + } +}; + +RegExp.escape = function(text) { + if (!arguments.callee.sRE) { + var specials = [ + '/', '.', '*', '+', '?', '|', + '(', ')', '[', ']', '{', '}', '\\' + ]; + arguments.callee.sRE = new RegExp( + '(\\' + specials.join('|\\') + ')', 'g' + ); + } + return text.replace(arguments.callee.sRE, '\\$1'); +} + +// This is a JS wrapper for the curl function made available in couch_js.c, +// it should be used in other JavaScripts that would like to make HTTP calls. + +var HTTP = (function() { + function parseCurl(string) { + var parts = string.split(/\r\n\r\n/); + var body = parts.pop(); + var header = parts.pop(); + var headers = header.split(/\n/); + + var status = /HTTP\/1.\d (\d*)/.exec(header)[1]; + return { + responseText: body, + status: parseInt(status), + getResponseHeader: function(key) { + var keymatcher = new RegExp(RegExp.escape(key), "i"); + for (var i in headers) { + var h = headers[i]; + if (keymatcher.test(h)) { + var value = h.substr(key.length+2); + return value.replace(/^\s+|\s+$/g,""); + } + } + return ""; + } + } + }; + return { + GET : function(url, body, headers) { + var st, urx = url, hx = (headers || null); + st = gethttp(urx, hx); + return parseCurl(st); + }, + HEAD : function(url, body, headers) { + var st, urx = url, hx = (headers || null); + st = headhttp(urx, hx); + return parseCurl(st); + }, + DELETE : function(url, body, headers) { + var st, urx = url, hx = (headers || null); + st = delhttp(urx, hx); + return parseCurl(st); + }, + MOVE : function(url, body, headers) { + var st, urx = url, hx = (headers || null); + st = movehttp(urx, hx); + return parseCurl(st); + }, + COPY : function(url, body, headers) { + var st, urx = url, hx = (headers || null); + st = copyhttp(urx, hx); + return parseCurl(st); + }, + POST : function(url, body, headers) { + var st, urx = url, bx = (body || ""), hx = (headers || {}); + hx['Content-Type'] = hx['Content-Type'] || "application/json"; + st = posthttp(urx, bx, hx); + return parseCurl(st); + }, + PUT : function(url, body, headers) { + var st, urx = url, bx = (body || ""), hx = (headers || {}); + hx['Content-Type'] = hx['Content-Type'] || "application/json"; + st = puthttp(urx, bx, hx); + return parseCurl(st); + } + }; +})(); + +// Monkeypatches to CouchDB client for use of curl. + +CouchDB.host = (typeof window == 'undefined' || !window) ? "127.0.0.1:5984" : window; + +CouchDB.request = function(method, uri, options) { + var full_uri = "http://" + CouchDB.host + uri; + options = options || {}; + var response = HTTP[method](full_uri, options.body, options.headers); + return response; +} + + +function toJSON(val) { + if (typeof(val) == "undefined") { + throw {error:"bad_value", reason:"Cannot encode 'undefined' value as JSON"}; + } + var subs = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', + '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; + if (typeof(val) == "xml") { // E4X support + val = val.toXMLString(); + } + return { + "Array": function(v) { + var buf = []; + for (var i = 0; i < v.length; i++) { + buf.push(toJSON(v[i])); + } + return "[" + buf.join(",") + "]"; + }, + "Boolean": function(v) { + return v.toString(); + }, + "Date": function(v) { + var f = function(n) { return n < 10 ? '0' + n : n } + return '"' + v.getUTCFullYear() + '-' + + f(v.getUTCMonth() + 1) + '-' + + f(v.getUTCDate()) + 'T' + + f(v.getUTCHours()) + ':' + + f(v.getUTCMinutes()) + ':' + + f(v.getUTCSeconds()) + 'Z"'; + }, + "Number": function(v) { + return isFinite(v) ? v.toString() : "null"; + }, + "Object": function(v) { + if (v === null) return "null"; + var buf = []; + for (var k in v) { + if (!v.hasOwnProperty(k) || typeof(k) !== "string" || v[k] === undefined) { + continue; + } + buf.push(toJSON(k, val) + ": " + toJSON(v[k])); + } + return "{" + buf.join(",") + "}"; + }, + "String": function(v) { + if (/["\\\x00-\x1f]/.test(v)) { + v = v.replace(/([\x00-\x1f\\"])/g, function(a, b) { + var c = subs[b]; + if (c) return c; + c = b.charCodeAt(); + return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); + }); + } + return '"' + v + '"'; + } + }[val != null ? val.constructor.name : "Object"](val); +} + + + +// *************** Test Framework Console Adapter ****************** // + +var p = print; +var numFailures = 0; + +function runAllBenchmarksConsole(dur, commit) { + var numBenches = 0; + p("Bench Duration: "+dur+"ms\n"); + for (var b in allBenches) { + p(b); + numBenches += 1; + var benchFun = allBenches[b]; + runBenchConsole(benchFun, dur, commit); + } + // p("Results: "+numFailures.toString() + " failures in "+numTests+" tests.") +}; + +function runBenchConsole(benchFun, duration, commit) { + var db = new CouchDB("bench_suite_db", {"X-Couch-Full-Commit":commit}); + try {db.createDb();} catch(e) {}; + + var acc = { + docs : 0, + }; + var loops = 0; + var start = new Date().getTime(); + try { + while(new Date().getTime() < start+duration) { + acc = benchFun(db, acc); + loops++; + } + p("OK"); + } catch(e) { + p("ERROR"); + p("Exception raised: "+e.toString()); + p("Backtrace: "+e.stack); + } + var duration = new Date().getTime() - start; + p(loops+" loops"); + p(acc.docs+" docs"); + p((acc.docs/(duration/1000))+" docs/sec\n"); +}; + + +// Use T to perform a test that returns false on failure and if the test fails, +// display the line that failed. +// Example: +// T(MyValue==1); +function T(arg1, arg2) { + if (!arg1) { + p("Assertion failed: "+(arg2 != null ? arg2 : arg1).toString()); + numFailures += 1 + } +} + +p("CouchDB Benchmarks"); +p("Host: "+CouchDB.host); + +try { + p("Version: "+CouchDB.getVersion()); + runAllBenchmarksConsole(10000,"false"); +} catch (e) { + p("error"); + p(e.toString()); +} + +p("Finished"); diff --git a/bench/benchbulk.sh b/bench/benchbulk.sh new file mode 100755 index 00000000..be1b080c --- /dev/null +++ b/bench/benchbulk.sh @@ -0,0 +1,69 @@ +#!/bin/sh -e +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# + +# usage: time benchbulk.sh +# it takes about 30 seconds to run on my old MacBook with bulksize 1000 + +BULKSIZE=100 +DOCSIZE=10 +INSERTS=10 +ROUNDS=10 +DBURL="http://127.0.0.1:5984/benchbulk" +POSTURL="$DBURL/_bulk_docs" + +function make_bulk_docs() { + ROW=0 + SIZE=$(($1-1)) + START=$2 + BODYSIZE=$3 + + BODY=$(printf "%0${BODYSIZE}d") + + echo '{"docs":[' + while [ $ROW -lt $SIZE ]; do + printf '{"_id":"%020d", "body":"'$BODY'"},' $(($ROW + $START)) + let ROW=ROW+1 + done + printf '{"_id":"%020d", "body":"'$BODY'"}' $(($ROW + $START)) + echo ']}' +} + +echo "Making $INSERTS bulk inserts of $BULKSIZE docs each" + +echo "Attempt to delete db at $DBURL" +curl -X DELETE $DBURL -w\\n + +echo "Attempt to create db at $DBURL" +curl -X PUT $DBURL -w\\n + +echo "Running $ROUNDS rounds of $INSERTS concurrent inserts to $POSTURL" +RUN=0 +while [ $RUN -lt $ROUNDS ]; do + + POSTS=0 + while [ $POSTS -lt $INSERTS ]; do + STARTKEY=$[ POSTS * BULKSIZE + RUN * BULKSIZE * INSERTS ] + echo "startkey $STARTKEY bulksize $BULKSIZE" + DOCS=$(make_bulk_docs $BULKSIZE $STARTKEY $DOCSIZE) + # echo $DOCS + echo $DOCS | curl -T - -X POST $POSTURL -w%{http_code}\ %{time_total}\ sec\\n -o out.file 2> /dev/null & + let POSTS=POSTS+1 + done + + echo "waiting" + wait + let RUN=RUN+1 +done + +curl $DBURL -w\\n
\ No newline at end of file diff --git a/bench/benches.js b/bench/benches.js new file mode 100644 index 00000000..2e0a92db --- /dev/null +++ b/bench/benches.js @@ -0,0 +1,62 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + + +var allBenches = {}; + +allBenches.single_doc_insert = function(db, acc) { + db.save({"foo":"bar"}); + acc.docs++; + return acc; +}; + +allBenches.batch_ok_doc_insert = function(db, acc) { + db.save({"foo":"bar"}, {"batch":"ok"}); + acc.docs++; + return acc; +}; + +function makeDocs(n) { + docs = []; + for (var i=0; i < n; i++) { + docs.push({"foo":"bar"}); + }; + return docs; +}; + +allBenches.bulk_doc_100 = function(db, acc) { + var docs = makeDocs(100); + db.bulkSave(docs); + acc.docs += 100; + return acc; +}; + +allBenches.bulk_doc_1000 = function(db, acc) { + var docs = makeDocs(1000); + db.bulkSave(docs); + acc.docs += 1000; + return acc; +}; + +allBenches.bulk_doc_5000 = function(db, acc) { + var docs = makeDocs(5000); + db.bulkSave(docs); + acc.docs += 5000; + return acc; +}; + +allBenches.bulk_doc_10000 = function(db, acc) { + var docs = makeDocs(10000); + db.bulkSave(docs); + acc.docs += 10000; + return acc; +};
\ No newline at end of file diff --git a/bench/out.file b/bench/out.file new file mode 100644 index 00000000..4b38feda --- /dev/null +++ b/bench/out.file @@ -0,0 +1 @@ +[{"id":"00000000000000000800","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000801","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000802","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000803","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000804","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000805","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000806","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000807","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000808","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000809","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000810","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000811","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000812","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000813","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000814","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000815","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000816","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000817","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000818","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000819","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000820","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000821","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000822","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000823","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000824","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000825","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000826","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000827","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000828","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000829","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000830","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000831","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000832","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000833","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000834","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000835","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000836","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000837","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000838","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000839","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000840","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000841","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000842","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000843","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000844","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000845","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000846","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000847","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000848","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000849","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000850","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000851","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000852","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000853","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000854","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000855","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000856","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000857","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000858","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000859","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000860","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000861","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000862","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000863","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000864","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000865","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000866","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000867","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000868","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000869","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000870","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000871","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000872","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000873","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000874","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000875","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000876","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000877","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000878","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000879","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000880","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000881","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000882","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000883","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000884","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000885","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000886","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000887","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000888","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000889","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000890","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000891","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000892","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000893","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000894","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000895","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000896","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000897","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000898","rev":"1-ca73793e047eb5e266cb27fd5952f89b"},{"id":"00000000000000000899","rev":"1-ca73793e047eb5e266cb27fd5952f89b"}] diff --git a/bench/runner.sh b/bench/runner.sh new file mode 100755 index 00000000..bdaffab5 --- /dev/null +++ b/bench/runner.sh @@ -0,0 +1,18 @@ +#!/bin/sh -e + +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +cat ../share/www/script/couch.js \ + benches.js \ + bench_lib.js \ + | ../src/couchdb/couchjs - |