Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] optimisation experiments #65

Closed
wants to merge 7 commits into from
110 changes: 110 additions & 0 deletions a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
var Benchmark = require('benchmark');
var ProtoDef = require("protodef").ProtoDef;
var proto=new ProtoDef();

var buf=new Buffer([0x1d,0x2d,0x3d,0x4d]);
var suite = new Benchmark.Suite;

var types=[
{
"name":"a",
"type":"i8"
},
{
"name":"b",
"type":"i8"
},
{
"name":"c",
"type":"i8"
},
{
"name":"d",
"type":"i8"
}
];

proto.addType("myContainer",["container",types]);

function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

function containerReaderBuild(typeArgs,proto){
const requireContext=typeArgs.filter(o => proto[`read${capitalizeFirstLetter(o.type)}`].length==3).length>0;
return eval(`((proto) =>
(buffer, offset${requireContext ? `,context`:``}) => {
var size=0;
var value2={};
${requireContext ? `
var value={};
value[".."]=context;
` :``}
var result;
${typeArgs.reduce((old, o) => old + `
result = proto.read${capitalizeFirstLetter(o.type)}(buffer, offset + size${requireContext ? `,value`:``});
${o.anon
? `if(result.value !== undefined)
Object.keys(result.value).forEach(key => ${requireContext ? `value[key]=` : ``}value2[key] = result[key]);`
: `${requireContext ? `value['${o.name}'] =` : ``} value2['${o.name}'] = result.value;`
}
size += result.size;
`, "")}
return {value:value2,size:size};
});`)(proto);
}
const generated = containerReaderBuild(types,proto);
console.log(generated(buf,0));


function myCustomContainer(buffer, offset, typeArgs, context){
var size=0;
var value={};

var result;
result=proto.readI8(buffer,offset+size);
value["a"]=result.value;
size+=result.size;
result=proto.readI8(buffer,offset+size);
value["b"]=result.value;
size+=result.size;
result=proto.readI8(buffer,offset+size);
value["c"]=result.value;
size+=result.size;
result=proto.readI8(buffer,offset+size);
value["d"]=result.value;
size+=result.size;

return {
value:value,
size:size
}
}
console.log(myCustomContainer(buf,0));

suite
.add('readContainer', function() {
return {
value: {
a: buf.readInt8(0),
b: buf.readInt8(1),
c: buf.readInt8(2),
d: buf.readInt8(3)
},
size:4
};
})
.add('protodef generated container', function() {
generated(buf,0,{});
})
.add('protodef myCustomContainer', function() {
myCustomContainer(buf,0,types,{});
})
.add('protodef readContainer', function() {
proto.readMyContainer(buf,0,{},{});
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.run({ 'async': false });

2 changes: 1 addition & 1 deletion benchmark/benchmark_all_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ it('reads',function() {
tests.data.forEach(test => {
test.subtypes.forEach(subType => {
subType.values.forEach((value) => {
proto.parsePacketBuffer(subType.type, value.buffer);
subType.read(value.buffer,0,{});
});
})
});
Expand Down
2 changes: 1 addition & 1 deletion benchmark/benchmark_by_kind.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ testData.forEach(tests => {
tests.data.forEach(test => {
test.subtypes.forEach(subType => {
subType.values.forEach((value) => {
proto.parsePacketBuffer(subType.type, value.buffer);
subType.read(value.buffer,0,{});
});
})
});
Expand Down
8 changes: 4 additions & 4 deletions benchmark/benchmark_by_subtype.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ var testData=require("../test/dataTypes/prepareTests").testData;
var proto=require("../test/dataTypes/prepareTests").proto;
var Benchmark = require('benchmark');

function testType(type,values)
function testType(type,values,read)
{
it('reads',function() {
var readSuite = new Benchmark.Suite;
readSuite.add('read', function () {
values.forEach((value) => {
proto.parsePacketBuffer(type, value.buffer);
read(value.buffer,0,{});
});
})
.on('cycle', function (event) {
Expand Down Expand Up @@ -39,10 +39,10 @@ testData.forEach(tests => {
describe(test.type,() => {
test.subtypes.forEach((subtype) => {
if(subtype.description) describe(subtype.description,() => {
testType(subtype.type,subtype.values);
testType(subtype.type,subtype.values,subtype.read);
});
else
testType(subtype.type,subtype.values);
testType(subtype.type,subtype.values,subtype.read);
});
});
});
Expand Down
15 changes: 8 additions & 7 deletions benchmark/benchmark_by_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var testData=require("../test/dataTypes/prepareTests").testData;
var proto=require("../test/dataTypes/prepareTests").proto;
var Benchmark = require('benchmark');

function testValue(type,value,buffer)
function testValue(type,value,buffer,read)
{
it('writes',function(){
var suite = new Benchmark.Suite;
Expand All @@ -16,8 +16,9 @@ function testValue(type,value,buffer)
});
it('reads',function(){
var suite = new Benchmark.Suite;

suite.add('read', function() {
proto.parsePacketBuffer(type,buffer)
read(buffer, 0,{});
})
.on('cycle', function(event) {
console.log(String(event.target));
Expand All @@ -26,15 +27,15 @@ function testValue(type,value,buffer)
});
}

function testType(type,values)
function testType(type,values,read)
{
values.forEach((value) => {
if(value.description)
describe(value.description,() => {
testValue(type,value.value,value.buffer);
testValue(type,value.value,value.buffer,read);
});
else
testValue(type,value.value,value.buffer);
testValue(type,value.value,value.buffer,read);
});
}

Expand All @@ -47,10 +48,10 @@ testData.forEach(tests => {
test.subtypes.forEach((subtype) => {
if(subtype.description)
describe(subtype.description,() => {
testType(subtype.type,subtype.values);
testType(subtype.type,subtype.values,subtype.read);
});
else
testType(subtype.type,subtype.values);
testType(subtype.type,subtype.values,subtype.read);
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion benchmark/benchmark_by_type.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ testData.forEach(tests => {
readSuite.add('read', function () {
test.subtypes.forEach(subType => {
subType.values.forEach((value) => {
proto.parsePacketBuffer(subType.type, value.buffer);
subType.read(value.buffer,0,{});
});
})
})
Expand Down
2 changes: 1 addition & 1 deletion benchmark/benchmark_unified.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ it('read/write',function() {
tests.data.forEach(test => {
test.subtypes.forEach(subType => {
subType.values.forEach((value) => {
proto.parsePacketBuffer(subType.type, value.buffer);
subType.read(value.buffer,0,{});
proto.createPacketBuffer(subType.type, value.value);
});
})
Expand Down
41 changes: 39 additions & 2 deletions src/datatypes/conditional.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
var { getField, getFieldInfo, tryDoc, PartialReadError} = require('../utils');

module.exports = {
'switch': [readSwitch, writeSwitch, sizeOfSwitch],
'option': [readOption, writeOption, sizeOfOption]
'switch': [readSwitch, writeSwitch, sizeOfSwitch, readSwitchGenerator],
'option': [readOption, writeOption, sizeOfOption, readOptionGenerator]
};

function capitalizeFirstLetter(string) {
return string[0].toUpperCase() + string.slice(1);
}

function readSwitchGenerator({compareTo,fields,compareToValue,...rest},proto){
return `
(buffer, offset, context) => {
var compareTo = ${compareToValue !==undefined ? `"${compareToValue}"` : `getField("${compareTo}", context)`};
switch(compareTo) {
${Object.keys(fields).reduce((old,key) =>
`${old} case ${key}:
return proto.read${capitalizeFirstLetter(fields[key])}(buffer, offset,context);
break;
`,"")}
default:
${rest.default ?
`return proto.read${capitalizeFirstLetter(rest.default)}(buffer, offset,context);` :
`throw new Error(compareTo + " has no associated fieldInfo in switch");`}
}
}`;
}

function readSwitch(buffer, offset, {compareTo,fields,compareToValue,...rest}, rootNode) {
compareTo = compareToValue!==undefined ? compareToValue : getField(compareTo, rootNode);
if (typeof fields[compareTo] === 'undefined' && typeof rest.default === "undefined")
Expand Down Expand Up @@ -36,6 +58,21 @@ function sizeOfSwitch(value, {compareTo,fields,compareToValue,...rest}, rootNode
return tryDoc(() => this.sizeOf(value, fieldInfo, rootNode),caseDefault ? "default" : compareTo);
}

function readOptionGenerator(typeArgs) {
return `(buffer,offset,context) => {
if(buffer.length<offset+1)
throw new PartialReadError();
var val = buffer.readUInt8(offset++);
if (val !== 0) {
var retval = proto.read${capitalizeFirstLetter(typeArgs)}(buffer, offset,context);
retval.size++;
return retval;
}
else
return {size: 1};
}`;
}

function readOption(buffer, offset, typeArgs, context) {
if(buffer.length<offset+1)
throw new PartialReadError();
Expand Down
23 changes: 9 additions & 14 deletions src/datatypes/numeric.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,15 @@ function writeLU64(value, buffer, offset) {

function generateFunctions(bufferReader,bufferWriter,size)
{
var reader=function(buffer, offset)
{
if(offset + size > buffer.length)
throw new PartialReadError();
var value = buffer[bufferReader](offset);
return {
value: value,
size: size
};
};
var writer=function(value, buffer, offset) {
buffer[bufferWriter](value, offset);
return offset + size;
};
var reader=eval("function f"+bufferReader+"(buffer,offset) {"+
" if(offset + "+size+" > buffer.length){"+
"throw new PartialReadError();}"+
"return {value:buffer."+bufferReader+"(offset,true),size:"+size+"};}" +
"f"+bufferReader+";");
var writer=eval("function f"+bufferWriter+"(value, buffer, offset) {"+
"buffer."+bufferWriter+"(value,offset);"+
"return offset+"+size+";}"+
"f"+bufferWriter+";");
return [reader, writer, size];
}

Expand Down
Loading