@vlasky/quoted-printable
Version:
Fast, robust RFC 2045 (Quoted-Printable) and RFC 2047 (Q-Encoding) encoder/decoder for Buffers in pure Javascript with an optional C++ binding. A fork of @ronomon/quoted-printable that supports Node.js 8+.
177 lines (165 loc) • 4.6 kB
JavaScript
var cpus = require('os').cpus();
var cpu = cpus[0].model;
var cores = cpus.length;
var concurrency = 1;
var QuotedPrintable = require('./index.js');
var Queue = require('@ronomon/queue');
var RNG = function(seed) {
var self = this;
if (seed === undefined) seed = Date.now();
if (typeof seed !== 'number' || Math.round(seed) !== seed || seed < 0) {
throw new Error('bad seed');
}
self.seed = seed % Math.pow(2, 31);
self.hash = self.seed;
};
RNG.prototype.random = function() {
var self = this;
self.hash = ((self.hash + 0x7ED55D16) + (self.hash << 12)) & 0xFFFFFFF;
self.hash = ((self.hash ^ 0xC761C23C) ^ (self.hash >>> 19)) & 0xFFFFFFF;
self.hash = ((self.hash + 0x165667B1) + (self.hash << 5)) & 0xFFFFFFF;
self.hash = ((self.hash + 0xD3A2646C) ^ (self.hash << 9)) & 0xFFFFFFF;
self.hash = ((self.hash + 0xFD7046C5) + (self.hash << 3)) & 0xFFFFFFF;
self.hash = ((self.hash ^ 0xB55A4F09) ^ (self.hash >>> 16)) & 0xFFFFFFF;
return (self.hash & 0xFFFFFFF) / 0x10000000;
};
var rng = new RNG();
var random = rng.random.bind(rng);
function generateBuffer(size) {
var buffer = Buffer.alloc(size);
while (size--) buffer[size] = Math.floor(random() * 256);
return buffer;
}
var bindings = [
{
name: 'Javascript',
decode: function(buffer, end) {
var options = { binding: QuotedPrintable.binding.javascript };
QuotedPrintable.decode(buffer, options);
end();
},
encode: function(buffer, end) {
var options = { binding: QuotedPrintable.binding.javascript };
QuotedPrintable.encode(buffer, options);
end();
}
},
{
name: 'Native',
decode: function(buffer, end) {
var options = { binding: QuotedPrintable.binding.native };
QuotedPrintable.decode(buffer, options);
end();
},
encode: function(buffer, end) {
var options = { binding: QuotedPrintable.binding.native };
QuotedPrintable.encode(buffer, options);
end();
}
}
];
var vectors = {};
var sizes = [
32,
128,
512,
2048,
8192,
32768
];
sizes.forEach(
function(size) {
var encode = [];
var decode = [];
var count = Math.ceil(1 * 1024 * 1024 / size);
while (count-- > 0) {
var buffer = generateBuffer(size);
encode.push(buffer);
decode.push(QuotedPrintable.encode(buffer));
}
vectors[size] = {
encode: encode,
decode: decode
};
}
);
function benchmark(binding, method, buffers, end) {
var now = Date.now();
var sum = 0;
var time = 0;
var count = 0;
var queue = new Queue(1);
queue.onData = function(buffer, end) {
var hrtime = process.hrtime();
binding[method](buffer,
function(error) {
if (error) return end(error);
var difference = process.hrtime(hrtime);
var ns = (difference[0] * 1e9) + difference[1];
// Count the number of data bytes that can be processed per second:
sum += buffer.length;
time += ns;
count++;
end();
}
);
};
queue.onEnd = function(error) {
if (error) return end(error);
var elapsed = Date.now() - now;
var latency = (time / count) / 1000000;
var throughput = sum / elapsed / 1000;
display([
binding.name + ':',
'Latency:',
latency.toFixed(3) + 'ms',
'Throughput:',
throughput.toFixed(2) + ' MB/s'
]);
// Rest between benchmarks to leave room for GC:
setTimeout(end, 100);
};
queue.concat(buffers);
queue.end();
}
function display(columns) {
var string = columns[0];
while (string.length < 15) string = ' ' + string;
string += ' ' + columns.slice(1).join(' ');
console.log(string);
}
console.log('');
display([ 'CPU:', cpu ]);
display([ 'Cores:', cores ]);
display([ 'Threads:', concurrency ]);
var queue = new Queue();
queue.onData = function(method, end) {
console.log('');
console.log('============================================================');
var queue = new Queue();
queue.onData = function(size, end) {
var buffers = vectors[size][method];
console.log('');
display([
method.slice(0, 1).toUpperCase() + method.slice(1) + ':',
buffers.length + ' x ' + size + ' Bytes'
]);
var queue = new Queue();
queue.onData = function(binding, end) {
benchmark(binding, method, buffers, end);
};
queue.onEnd = end;
queue.concat(bindings);
queue.end();
};
queue.onEnd = end;
queue.concat(sizes);
queue.end();
};
queue.onEnd = function(error) {
if (error) throw error;
console.log('');
};
queue.push('encode');
queue.push('decode');
queue.end();