bench-multipart-fields-100mb-big.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. 'use strict';
  2. function createMultipartBuffers(boundary, sizes) {
  3. const bufs = [];
  4. for (let i = 0; i < sizes.length; ++i) {
  5. const mb = sizes[i] * 1024 * 1024;
  6. bufs.push(Buffer.from([
  7. `--${boundary}`,
  8. `content-disposition: form-data; name="field${i + 1}"`,
  9. '',
  10. '0'.repeat(mb),
  11. '',
  12. ].join('\r\n')));
  13. }
  14. bufs.push(Buffer.from([
  15. `--${boundary}--`,
  16. '',
  17. ].join('\r\n')));
  18. return bufs;
  19. }
  20. const boundary = '-----------------------------168072824752491622650073';
  21. const buffers = createMultipartBuffers(boundary, [
  22. 10,
  23. 10,
  24. 10,
  25. 20,
  26. 50,
  27. ]);
  28. const calls = {
  29. partBegin: 0,
  30. headerField: 0,
  31. headerValue: 0,
  32. headerEnd: 0,
  33. headersEnd: 0,
  34. partData: 0,
  35. partEnd: 0,
  36. end: 0,
  37. };
  38. const moduleName = process.argv[2];
  39. switch (moduleName) {
  40. case 'busboy': {
  41. const busboy = require('busboy');
  42. const parser = busboy({
  43. limits: {
  44. fieldSizeLimit: Infinity,
  45. },
  46. headers: {
  47. 'content-type': `multipart/form-data; boundary=${boundary}`,
  48. },
  49. });
  50. parser.on('field', (name, val, info) => {
  51. ++calls.partBegin;
  52. ++calls.partData;
  53. ++calls.partEnd;
  54. }).on('close', () => {
  55. ++calls.end;
  56. console.timeEnd(moduleName);
  57. });
  58. console.time(moduleName);
  59. for (const buf of buffers)
  60. parser.write(buf);
  61. break;
  62. }
  63. case 'formidable': {
  64. const { MultipartParser } = require('formidable');
  65. const parser = new MultipartParser();
  66. parser.initWithBoundary(boundary);
  67. parser.on('data', ({ name }) => {
  68. ++calls[name];
  69. if (name === 'end')
  70. console.timeEnd(moduleName);
  71. });
  72. console.time(moduleName);
  73. for (const buf of buffers)
  74. parser.write(buf);
  75. break;
  76. }
  77. case 'multiparty': {
  78. const { Readable } = require('stream');
  79. const { Form } = require('multiparty');
  80. const form = new Form({
  81. maxFieldsSize: Infinity,
  82. maxFields: Infinity,
  83. maxFilesSize: Infinity,
  84. autoFields: false,
  85. autoFiles: false,
  86. });
  87. const req = new Readable({ read: () => {} });
  88. req.headers = {
  89. 'content-type': `multipart/form-data; boundary=${boundary}`,
  90. };
  91. function hijack(name, fn) {
  92. const oldFn = form[name];
  93. form[name] = function() {
  94. fn();
  95. return oldFn.apply(this, arguments);
  96. };
  97. }
  98. hijack('onParseHeaderField', () => {
  99. ++calls.headerField;
  100. });
  101. hijack('onParseHeaderValue', () => {
  102. ++calls.headerValue;
  103. });
  104. hijack('onParsePartBegin', () => {
  105. ++calls.partBegin;
  106. });
  107. hijack('onParsePartData', () => {
  108. ++calls.partData;
  109. });
  110. hijack('onParsePartEnd', () => {
  111. ++calls.partEnd;
  112. });
  113. form.on('close', () => {
  114. ++calls.end;
  115. console.timeEnd(moduleName);
  116. }).on('part', (p) => p.resume());
  117. console.time(moduleName);
  118. form.parse(req);
  119. for (const buf of buffers)
  120. req.push(buf);
  121. req.push(null);
  122. break;
  123. }
  124. default:
  125. if (moduleName === undefined)
  126. console.error('Missing parser module name');
  127. else
  128. console.error(`Invalid parser module name: ${moduleName}`);
  129. process.exit(1);
  130. }