Skip to content

Commit

Permalink
Crazy speedup with non recursion based js parser
Browse files Browse the repository at this point in the history
  • Loading branch information
christkv committed Jul 3, 2011
1 parent 89509ba commit 28ecff2
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 41 deletions.
46 changes: 23 additions & 23 deletions benchmark/bson_benchmark.js
@@ -1,4 +1,4 @@
var BSON = require('../lib/mongodb').BSONNative.BSON,
// var BSON = require('../lib/mongodb').BSONNative.BSON,
debug = require('util').debug,
inspect = require('util').inspect;
var BSON = require('../lib/mongodb').BSONPure.BSON;
Expand All @@ -9,15 +9,15 @@ var COUNT = 10000;
// var COUNT = 1;
var object = {
string: "Strings are great",
// decimal: 3.14159265,
// bool: true,
// integer: 5,
// subObject: {
// moreText: "Bacon ipsum dolor sit amet cow pork belly rump ribeye pastrami andouille. Tail hamburger pork belly, drumstick flank salami t-bone sirloin pork chop ribeye ham chuck pork loin shankle. Ham fatback pork swine, sirloin shankle short loin andouille shank sausage meatloaf drumstick. Pig chicken cow bresaola, pork loin jerky meatball tenderloin brisket strip steak jowl spare ribs. Biltong sirloin pork belly boudin, bacon pastrami rump chicken. Jowl rump fatback, biltong bacon t-bone turkey. Turkey pork loin boudin, tenderloin jerky beef ribs pastrami spare ribs biltong pork chop beef.",
// longKeylongKeylongKeylongKeylongKeylongKey: "Pork belly boudin shoulder ribeye pork chop brisket biltong short ribs. Salami beef pork belly, t-bone sirloin meatloaf tail jowl spare ribs. Sirloin biltong bresaola cow turkey. Biltong fatback meatball, bresaola tail shankle turkey pancetta ham ribeye flank bacon jerky pork chop. Boudin sirloin shoulder, salami swine flank jerky t-bone pork chop pork beef tongue. Bresaola ribeye jerky andouille. Ribeye ground round sausage biltong beef ribs chuck, shank hamburger chicken short ribs spare ribs tenderloin meatloaf pork loin."
// },
// subArray: [1,2,3,4,5,6,7,8,9,10],
// anotherString: "another string"
decimal: 3.14159265,
bool: true,
integer: 5,
subObject: {
moreText: "Bacon ipsum dolor sit amet cow pork belly rump ribeye pastrami andouille. Tail hamburger pork belly, drumstick flank salami t-bone sirloin pork chop ribeye ham chuck pork loin shankle. Ham fatback pork swine, sirloin shankle short loin andouille shank sausage meatloaf drumstick. Pig chicken cow bresaola, pork loin jerky meatball tenderloin brisket strip steak jowl spare ribs. Biltong sirloin pork belly boudin, bacon pastrami rump chicken. Jowl rump fatback, biltong bacon t-bone turkey. Turkey pork loin boudin, tenderloin jerky beef ribs pastrami spare ribs biltong pork chop beef.",
longKeylongKeylongKeylongKeylongKeylongKey: "Pork belly boudin shoulder ribeye pork chop brisket biltong short ribs. Salami beef pork belly, t-bone sirloin meatloaf tail jowl spare ribs. Sirloin biltong bresaola cow turkey. Biltong fatback meatball, bresaola tail shankle turkey pancetta ham ribeye flank bacon jerky pork chop. Boudin sirloin shoulder, salami swine flank jerky t-bone pork chop pork beef tongue. Bresaola ribeye jerky andouille. Ribeye ground round sausage biltong beef ribs chuck, shank hamburger chicken short ribs spare ribs tenderloin meatloaf pork loin."
},
subArray: [1,2,3,4,5,6,7,8,9,10],
anotherString: "another string"
}

var x, start, end, i
Expand Down Expand Up @@ -45,19 +45,19 @@ console.log("time = ", end - start, "ms -", COUNT * 1000 / (end - start), " ops/
// end = new Date
// console.log("json size (chars): ", objectJSON.length)
// console.log("time = ", end - start, "ms -", COUNT * 1000 / (end - start), " ops/sec")
//
//
// console.log(COUNT + " BSON.deserialize(objectBSON)")
// start = new Date
//
// for (i=COUNT; --i>=0; ) {
// x = BSON.deserialize(objectBSON)
// }
//
// end = new Date
// console.log("time = ", end - start, "ms -", COUNT * 1000 / (end - start), " ops/sec")
//
//


console.log(COUNT + " BSON.deserialize(objectBSON)")
start = new Date

for (i=COUNT; --i>=0; ) {
x = BSON.deserialize(objectBSON)
}

end = new Date
console.log("time = ", end - start, "ms -", COUNT * 1000 / (end - start), " ops/sec")


// console.log(COUNT + " JSON.parse(objectJSON)")
// start = new Date
//
Expand Down
106 changes: 88 additions & 18 deletions lib/mongodb/bson/bson.js
Expand Up @@ -155,6 +155,7 @@ BSON.encodeObjectNoRec = function(buffer, object, checkKeys) {
var currentObject = object;
var keys = null;
var size = 0;
var objectIndex = 0;

// Pack the size of the total buffer length
size = buffer.length;
Expand Down Expand Up @@ -184,29 +185,77 @@ BSON.encodeObjectNoRec = function(buffer, object, checkKeys) {
// name = Array.isArray(currentObject) ? // null : name;

if(Array.isArray(value)) {
index += (name != null ? (name.length + 1) : 0) + (4 + 1) + 1;
// Write the type
buffer[index++] = BSON.BSON_DATA_ARRAY;
// Write the name
if(name != null) {
buffer.write(name, index, 'binary');
// Encode the name
index = index + name.length + 1;
buffer[index] = 0;
}

// Save index to allow for writing in the size
objectIndex = index;
// Ajust the index to ensure we can write the size of the object
index = index + 4;

// Push object on stack to process sub fields
stack.push({keys:keys, object:currentObject});
currentObject = value;
keys = Object.keys(value)
break;
} else if(typeof value == 'number' && value === parseInt(value, 10)) {
// Write the type
buffer[index++] = BSON.BSON_DATA_INT;
// Write the name
if(name != null) {
buffer.write(name, index, 'binary');
// Encode the name
index = index + name.length + 1;
buffer[index] = 0;
}

if(value >= BSON.BSON_INT32_MAX || value < BSON.BSON_INT32_MIN) {
// index += (name != null ? (name.length + 1) : 0) + (8 + 1);
// debug("---------------- :: " + name + " = " + (typeof value) + " = " + (index - old));
index += 8;
} else {
// index += (name != null ? (name.length + 1) : 0) + (4 + 1);
// debug("---------------- :: " + name + " = " + (typeof value) + " = " + (index - old));
index += 4;
// Write the int value to the buffer
buffer[index + 3] = (value >> 24) & 0xff;
buffer[index + 2] = (value >> 16) & 0xff;
buffer[index + 1] = (value >> 8) & 0xff;
buffer[index] = value & 0xff;
// Ajust the index
index = index + 4;
}
} else if(typeof value == 'number' || toString.call(value) === '[object Number]') {
index += (name != null ? (name.length + 1) : 0) + (8 + 1);
// debug("---------------- :: " + name + " = " + (typeof value) + " = " + (index - old));
// index += 8;
// Write the type
buffer[index++] = BSON.BSON_DATA_NUMBER;
// Write the name
if(name != null) {
buffer.write(name, index, 'binary');
// Encode the name
index = index + name.length + 1;
buffer[index] = 0;
}

// Write float
ieee754.writeIEEE754(buffer, value, index, 'little', 52, 8);
// Ajust index
index = index + 8;
} else if(typeof value == 'boolean' || toString.call(value) === '[object Boolean]') {
index += (name != null ? (name.length + 1) : 0) + (1 + 1);
// debug("---------------- :: " + name + " = " + (typeof value) + " = " + (index - old));
// index += 1;
// Write the type
buffer[index++] = BSON.BSON_DATA_NUMBER;
// Write the name
if(name != null) {
buffer.write(name, index, 'binary');
// Encode the name
index = index + name.length + 1;
buffer[index] = 0;
}

buffer[index++] = value ? 1 : 0;
} else if(typeof value == 'string') {
// Write the type
buffer[index++] = BSON.BSON_DATA_STRING;
Expand Down Expand Up @@ -234,7 +283,22 @@ BSON.encodeObjectNoRec = function(buffer, object, checkKeys) {
// Write zero
buffer[index++] = 0;
} else if(typeof value == 'object') {
index += (name != null ? (name.length + 1) : 0) + (4 + 1 + 1);
// Write the type
buffer[index++] = BSON.BSON_DATA_OBJECT;
// Write the name
if(name != null) {
buffer.write(name, index, 'binary');
// Encode the name
index = index + name.length + 1;
buffer[index] = 0;
}

// Save index to allow for writing in the size
objectIndex = index;
// Ajust the index to ensure we can write the size of the object
index = index + 4;

// Push object on stack to process sub fields
stack.push({keys:keys, object:currentObject});
currentObject = value;
keys = Object.keys(value)
Expand All @@ -243,7 +307,14 @@ BSON.encodeObjectNoRec = function(buffer, object, checkKeys) {

// Finished up the object
if(keys.length == 0) {
// debug("==================== reset")
// Calculate size
size = index - objectIndex + 1;
// Write the size of the string to buffer
buffer[objectIndex + 3] = (size >> 24) & 0xff;
buffer[objectIndex + 2] = (size >> 16) & 0xff;
buffer[objectIndex + 1] = (size >> 8) & 0xff;
buffer[objectIndex] = size & 0xff;
// debug("==================== reset :: " + (index - objectIndex))
finished = true;
}
}
Expand Down Expand Up @@ -272,12 +343,11 @@ BSON.serialize = function serialize(object, checkKeys, asBuffer) {
var buffer = new Buffer(calculatedSize);
// Encode the object using single allocated buffer and no recursion
BSON.encodeObjectNoRec(buffer, object, checkKeys == null ? false : true);

var finalBuffer = buffer;

// // debug("--------------------------------------------------------- buffers")
// debug("--------------------------------------------------------- buffers")
// // debug(inspect(buffer.toString('binar')))
// // BinaryParser.hlprint(buffer.toString('binary'))
// BinaryParser.hlprint(buffer.toString('binary'))
//
// var totalLength = BSON.encodeObject(buffers, null, object, checkKeys == null ? false : checkKeys);
// var finalBuffer = new Buffer(totalLength);
Expand All @@ -290,9 +360,9 @@ BSON.serialize = function serialize(object, checkKeys, asBuffer) {
// index = index + buffers[i].length;
// }
//
// // debug("--------------------------------------------------------- finalBuffer")
// // BinaryParser.hlprint(finalBuffer.toString('binary'))
// // debug(inspect(finalBuffer))
// debug("--------------------------------------------------------- finalBuffer")
// BinaryParser.hlprint(finalBuffer.toString('binary'))
// debug(inspect(finalBuffer))

return asBuffer ? finalBuffer : finalBuffer.toString('binary')
} else {
Expand Down

0 comments on commit 28ecff2

Please sign in to comment.