summaryrefslogtreecommitdiffstats
path: root/fastify-busboy/bench/dicer
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js60
-rw-r--r--fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js71
-rw-r--r--fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js57
-rw-r--r--fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js78
-rw-r--r--fastify-busboy/bench/dicer/parted-bench-multipart-parser.js65
-rw-r--r--fastify-busboy/bench/dicer/parted-multipart.js486
6 files changed, 817 insertions, 0 deletions
diff --git a/fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js b/fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js
new file mode 100644
index 0000000..d24f599
--- /dev/null
+++ b/fastify-busboy/bench/dicer/dicer-bench-multipart-parser.js
@@ -0,0 +1,60 @@
+'use strict'
+
+const Dicer = require('../../deps/dicer/lib/Dicer')
+
+function createMultipartBuffer(boundary, size) {
+ const head =
+ '--' + boundary + '\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--' + boundary + '--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 0, 'ascii');
+ buffer.write(tail, buffer.length - tail.length, 'ascii');
+ return buffer;
+}
+
+for (var i = 0, il = 10; i < il; i++) { // eslint-disable-line no-var
+ const boundary = '-----------------------------168072824752491622650073',
+ d = new Dicer({ boundary: boundary }),
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ {
+ partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+ d.on('part', function (p) {
+ callbacks.partBegin++;
+ p.on('header', function (header) {
+ /*for (var h in header)
+ console.log('Part header: k: ' + inspect(h) + ', v: ' + inspect(header[h]));*/
+ });
+ p.on('data', function (data) {
+ callbacks.partData++;
+ //console.log('Part data: ' + inspect(data.toString()));
+ });
+ p.on('end', function () {
+ //console.log('End of part\n');
+ callbacks.partEnd++;
+ });
+ });
+ d.on('end', function () {
+ //console.log('End of parts');
+ callbacks.end++;
+ });
+
+ const start = +new Date();
+ d.write(buffer);
+ const duration = +new Date - start;
+ const mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+ console.log(mbPerSec + ' mb/sec');
+}
diff --git a/fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js b/fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js
new file mode 100644
index 0000000..0470771
--- /dev/null
+++ b/fastify-busboy/bench/dicer/formidable-bench-multipart-parser.js
@@ -0,0 +1,71 @@
+'use strict'
+
+require('../node_modules/formidable/test/common');
+var multipartParser = require('../node_modules/formidable/lib/multipart_parser'),
+ MultipartParser = multipartParser.MultipartParser,
+ parser = new MultipartParser(),
+ boundary = '-----------------------------168072824752491622650073',
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+parser.initWithBoundary(boundary);
+parser.onHeaderField = function() {
+ callbacks.headerField++;
+};
+
+parser.onHeaderValue = function() {
+ callbacks.headerValue++;
+};
+
+parser.onPartBegin = function() {
+ callbacks.partBegin++;
+};
+
+parser.onPartData = function() {
+ callbacks.partData++;
+};
+
+parser.onPartEnd = function() {
+ callbacks.partEnd++;
+};
+
+parser.onEnd = function() {
+ callbacks.end++;
+};
+
+var start = +new Date(),
+ nparsed = parser.write(buffer),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
diff --git a/fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js b/fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js
new file mode 100644
index 0000000..40ca00b
--- /dev/null
+++ b/fastify-busboy/bench/dicer/multipartser-bench-multipart-parser.js
@@ -0,0 +1,57 @@
+'use strict'
+
+var multipartser = require('multipartser'),
+ boundary = '-----------------------------168072824752491622650073',
+ parser = multipartser(),
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+parser.boundary( boundary );
+
+parser.on( 'part', function ( part ) {
+});
+
+parser.on( 'end', function () {
+ //console.log( 'completed parsing' );
+});
+
+parser.on( 'error', function ( error ) {
+ console.error( error );
+});
+
+var start = +new Date(),
+ nparsed = parser.data(buffer),
+ nend = parser.end(),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
diff --git a/fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js b/fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js
new file mode 100644
index 0000000..ab79ec0
--- /dev/null
+++ b/fastify-busboy/bench/dicer/multiparty-bench-multipart-parser.js
@@ -0,0 +1,78 @@
+'use strict'
+
+var assert = require('node:assert'),
+ Form = require('multiparty').Form,
+ boundary = '-----------------------------168072824752491622650073',
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+var form = new Form({ boundary: boundary });
+
+hijack('onParseHeaderField', function() {
+ callbacks.headerField++;
+});
+
+hijack('onParseHeaderValue', function() {
+ callbacks.headerValue++;
+});
+
+hijack('onParsePartBegin', function() {
+ callbacks.partBegin++;
+});
+
+hijack('onParsePartData', function() {
+ callbacks.partData++;
+});
+
+hijack('onParsePartEnd', function() {
+ callbacks.partEnd++;
+});
+
+form.on('finish', function() {
+ callbacks.end++;
+});
+
+var start = new Date();
+form.write(buffer, function(err) {
+ var duration = new Date() - start;
+ assert.ifError(err);
+ var mbPerSec = (mb / (duration / 1000)).toFixed(2);
+ console.log(mbPerSec+' mb/sec');
+});
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
+
+function hijack(name, fn) {
+ var oldFn = form[name];
+ form[name] = function() {
+ fn();
+ return oldFn.apply(this, arguments);
+ };
+}
diff --git a/fastify-busboy/bench/dicer/parted-bench-multipart-parser.js b/fastify-busboy/bench/dicer/parted-bench-multipart-parser.js
new file mode 100644
index 0000000..e0a4670
--- /dev/null
+++ b/fastify-busboy/bench/dicer/parted-bench-multipart-parser.js
@@ -0,0 +1,65 @@
+'use strict'
+
+// A special, edited version of the multipart parser from parted is needed here
+// because otherwise it attempts to do some things above and beyond just parsing
+// -- like saving to disk and whatnot
+
+var assert = require('node:assert');
+var Parser = require('./parted-multipart'),
+ boundary = '-----------------------------168072824752491622650073',
+ parser = new Parser('boundary=' + boundary),
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+parser.on('header', function() {
+ //callbacks.headerField++;
+});
+
+parser.on('data', function() {
+ //callbacks.partBegin++;
+});
+
+parser.on('part', function() {
+
+});
+
+parser.on('end', function() {
+ //callbacks.end++;
+});
+
+var start = +new Date(),
+ nparsed = parser.write(buffer),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+//assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = Buffer.allocUnsafe(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ /*for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }*/
+});
diff --git a/fastify-busboy/bench/dicer/parted-multipart.js b/fastify-busboy/bench/dicer/parted-multipart.js
new file mode 100644
index 0000000..f214ff4
--- /dev/null
+++ b/fastify-busboy/bench/dicer/parted-multipart.js
@@ -0,0 +1,486 @@
+'use strict'
+
+/**
+ * Parted (https://github.com/chjj/parted)
+ * A streaming multipart state parser.
+ * Copyright (c) 2011, Christopher Jeffrey. (MIT Licensed)
+ */
+
+var fs = require('node:fs')
+ , path = require('node:path')
+ , EventEmitter = require('node:events').EventEmitter
+ , StringDecoder = require('node:string_decoder').StringDecoder
+ , set = require('qs').set
+ , each = Array.prototype.forEach;
+
+/**
+ * Character Constants
+ */
+
+var DASH = '-'.charCodeAt(0)
+ , CR = '\r'.charCodeAt(0)
+ , LF = '\n'.charCodeAt(0)
+ , COLON = ':'.charCodeAt(0)
+ , SPACE = ' '.charCodeAt(0);
+
+/**
+ * Parser
+ */
+
+var Parser = function(type, options) {
+ if (!(this instanceof Parser)) {
+ return new Parser(type, options);
+ }
+
+ EventEmitter.call(this);
+
+ this.writable = true;
+ this.readable = true;
+
+ this.options = options || {};
+
+ var key = grab(type, 'boundary');
+ if (!key) {
+ return this._error('No boundary key found.');
+ }
+
+ this.key = Buffer.allocUnsafe('\r\n--' + key);
+
+ this._key = {};
+ each.call(this.key, function(ch) {
+ this._key[ch] = true;
+ }, this);
+
+ this.state = 'start';
+ this.pending = 0;
+ this.written = 0;
+ this.writtenDisk = 0;
+ this.buff = Buffer.allocUnsafe(200);
+
+ this.preamble = true;
+ this.epilogue = false;
+
+ this._reset();
+};
+
+Parser.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Parsing
+ */
+
+Parser.prototype.write = function(data) {
+ if (!this.writable
+ || this.epilogue) return;
+
+ try {
+ this._parse(data);
+ } catch (e) {
+ this._error(e);
+ }
+
+ return true;
+};
+
+Parser.prototype.end = function(data) {
+ if (!this.writable) return;
+
+ if (data) this.write(data);
+
+ if (!this.epilogue) {
+ return this._error('Message underflow.');
+ }
+
+ return true;
+};
+
+Parser.prototype._parse = function(data) {
+ var i = 0
+ , len = data.length
+ , buff = this.buff
+ , key = this.key
+ , ch
+ , val
+ , j;
+
+ for (; i < len; i++) {
+ if (this.pos >= 200) {
+ return this._error('Potential buffer overflow.');
+ }
+
+ ch = data[i];
+
+ switch (this.state) {
+ case 'start':
+ switch (ch) {
+ case DASH:
+ this.pos = 3;
+ this.state = 'key';
+ break;
+ default:
+ break;
+ }
+ break;
+ case 'key':
+ if (this.pos === key.length) {
+ this.state = 'key_end';
+ i--;
+ } else if (ch !== key[this.pos]) {
+ if (this.preamble) {
+ this.state = 'start';
+ i--;
+ } else {
+ this.state = 'body';
+ val = this.pos - i;
+ if (val > 0) {
+ this._write(key.slice(0, val));
+ }
+ i--;
+ }
+ } else {
+ this.pos++;
+ }
+ break;
+ case 'key_end':
+ switch (ch) {
+ case CR:
+ this.state = 'key_line_end';
+ break;
+ case DASH:
+ this.state = 'key_dash_end';
+ break;
+ default:
+ return this._error('Expected CR or DASH.');
+ }
+ break;
+ case 'key_line_end':
+ switch (ch) {
+ case LF:
+ if (this.preamble) {
+ this.preamble = false;
+ } else {
+ this._finish();
+ }
+ this.state = 'header_name';
+ this.pos = 0;
+ break;
+ default:
+ return this._error('Expected CR.');
+ }
+ break;
+ case 'key_dash_end':
+ switch (ch) {
+ case DASH:
+ this.epilogue = true;
+ this._finish();
+ return;
+ default:
+ return this._error('Expected DASH.');
+ }
+ case 'header_name':
+ switch (ch) {
+ case COLON:
+ this.header = buff.toString('ascii', 0, this.pos);
+ this.pos = 0;
+ this.state = 'header_val';
+ break;
+ default:
+ buff[this.pos++] = ch | 32;
+ break;
+ }
+ break;
+ case 'header_val':
+ switch (ch) {
+ case CR:
+ this.state = 'header_val_end';
+ break;
+ case SPACE:
+ if (this.pos === 0) {
+ break;
+ }
+ // FALL-THROUGH
+ default:
+ buff[this.pos++] = ch;
+ break;
+ }
+ break;
+ case 'header_val_end':
+ switch (ch) {
+ case LF:
+ val = buff.toString('ascii', 0, this.pos);
+ this._header(this.header, val);
+ this.pos = 0;
+ this.state = 'header_end';
+ break;
+ default:
+ return this._error('Expected LF.');
+ }
+ break;
+ case 'header_end':
+ switch (ch) {
+ case CR:
+ this.state = 'head_end';
+ break;
+ default:
+ this.state = 'header_name';
+ i--;
+ break;
+ }
+ break;
+ case 'head_end':
+ switch (ch) {
+ case LF:
+ this.state = 'body';
+ i++;
+ if (i >= len) return;
+ data = data.slice(i);
+ i = -1;
+ len = data.length;
+ break;
+ default:
+ return this._error('Expected LF.');
+ }
+ break;
+ case 'body':
+ switch (ch) {
+ case CR:
+ if (i > 0) {
+ this._write(data.slice(0, i));
+ }
+ this.pos = 1;
+ this.state = 'key';
+ data = data.slice(i);
+ i = 0;
+ len = data.length;
+ break;
+ default:
+ // boyer-moore-like algorithm
+ // at felixge's suggestion
+ while ((j = i + key.length - 1) < len) {
+ if (this._key[data[j]]) break;
+ i = j;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ if (this.state === 'body') {
+ this._write(data);
+ }
+};
+
+Parser.prototype._header = function(name, val) {
+ /*if (name === 'content-disposition') {
+ this.field = grab(val, 'name');
+ this.file = grab(val, 'filename');
+
+ if (this.file) {
+ this.data = stream(this.file, this.options.path);
+ } else {
+ this.decode = new StringDecoder('utf8');
+ this.data = '';
+ }
+ }*/
+
+ return this.emit('header', name, val);
+};
+
+Parser.prototype._write = function(data) {
+ /*if (this.data == null) {
+ return this._error('No disposition.');
+ }
+
+ if (this.file) {
+ this.data.write(data);
+ this.writtenDisk += data.length;
+ } else {
+ this.data += this.decode.write(data);
+ this.written += data.length;
+ }*/
+
+ this.emit('data', data);
+};
+
+Parser.prototype._reset = function() {
+ this.pos = 0;
+ this.decode = null;
+ this.field = null;
+ this.data = null;
+ this.file = null;
+ this.header = null;
+};
+
+Parser.prototype._error = function(err) {
+ this.destroy();
+ this.emit('error', typeof err === 'string'
+ ? new Error(err)
+ : err);
+};
+
+Parser.prototype.destroy = function(err) {
+ this.writable = false;
+ this.readable = false;
+ this._reset();
+};
+
+Parser.prototype._finish = function() {
+ var self = this
+ , field = this.field
+ , data = this.data
+ , file = this.file
+ , part;
+
+ this.pending++;
+
+ this._reset();
+
+ if (data && data.path) {
+ part = data.path;
+ data.end(next);
+ } else {
+ part = data;
+ next();
+ }
+
+ function next() {
+ if (!self.readable) return;
+
+ self.pending--;
+
+ self.emit('part', field, part);
+
+ if (data && data.path) {
+ self.emit('file', field, part, file);
+ }
+
+ if (self.epilogue && !self.pending) {
+ self.emit('end');
+ self.destroy();
+ }
+ }
+};
+
+/**
+ * Uploads
+ */
+
+Parser.root = process.platform === 'win32'
+ ? 'C:/Temp'
+ : '/tmp';
+
+/**
+ * Middleware
+ */
+
+Parser.middleware = function(options) {
+ options = options || {};
+ return function(req, res, next) {
+ if (options.ensureBody) {
+ req.body = {};
+ }
+
+ if (req.method === 'GET'
+ || req.method === 'HEAD'
+ || req._multipart) return next();
+
+ req._multipart = true;
+
+ var type = req.headers['content-type'];
+
+ if (type) type = type.split(';', 1)[0].trim().toLowerCase();
+
+ if (type === 'multipart/form-data') {
+ Parser.handle(req, res, next, options);
+ } else {
+ next();
+ }
+ };
+};
+
+/**
+ * Handler
+ */
+
+Parser.handle = function(req, res, next, options) {
+ var parser = new Parser(req.headers['content-type'], options)
+ , diskLimit = options.diskLimit
+ , limit = options.limit
+ , parts = {}
+ , files = {};
+
+ parser.on('error', function(err) {
+ req.destroy();
+ next(err);
+ });
+
+ parser.on('part', function(field, part) {
+ set(parts, field, part);
+ });
+
+ parser.on('file', function(field, path, name) {
+ set(files, field, {
+ path: path,
+ name: name,
+ toString: function() {
+ return path;
+ }
+ });
+ });
+
+ parser.on('data', function() {
+ if (this.writtenDisk > diskLimit || this.written > limit) {
+ this.emit('error', new Error('Overflow.'));
+ this.destroy();
+ }
+ });
+
+ parser.on('end', next);
+
+ req.body = parts;
+ req.files = files;
+ req.pipe(parser);
+};
+
+/**
+ * Helpers
+ */
+
+var isWindows = process.platform === 'win32';
+
+var stream = function(name, dir) {
+ var ext = path.extname(name) || ''
+ , name = path.basename(name, ext) || ''
+ , dir = dir || Parser.root
+ , tag;
+
+ tag = Math.random().toString(36).substring(2);
+
+ name = name.substring(0, 200) + '.' + tag;
+ name = path.join(dir, name) + ext.substring(0, 6);
+ name = name.replace(/\0/g, '');
+
+ if (isWindows) {
+ name = name.replace(/[:*<>|"?]/g, '');
+ }
+
+ return fs.createWriteStream(name);
+};
+
+var grab = function(str, name) {
+ if (!str) return;
+
+ var rx = new RegExp('\\b' + name + '\\s*=\\s*("[^"]+"|\'[^\']+\'|[^;,]+)', 'i')
+ , cap = rx.exec(str);
+
+ if (cap) {
+ return cap[1].trim().replace(/^['"]|['"]$/g, '');
+ }
+};
+
+/**
+ * Expose
+ */
+
+module.exports = Parser;