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

add benchmark for larger payloads #137

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions benchmarks/_results/Busboy_comparison-busboy-Node_12.json

This file was deleted.

10 changes: 0 additions & 10 deletions benchmarks/_results/Busboy_comparison-busboy-Node_16.json

This file was deleted.

10 changes: 10 additions & 0 deletions benchmarks/_results/Busboy_comparison-busboy-Node_20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"runtimeVersion": "20.9.0, V8 11.3.244.8-node.16",
"benchmarkName": "Busboy comparison",
"benchmarkEntryName": "busboy",
"benchmarkCycles": 500,
"benchmarkCycleSamples": 50,
"warmupCycles": 50,
"meanTimeNs": 259789.77117937893,
"meanTimeMs": 0.25978977117937896
}
10 changes: 0 additions & 10 deletions benchmarks/_results/Busboy_comparison-fastify-busboy-Node_16.json

This file was deleted.

10 changes: 10 additions & 0 deletions benchmarks/_results/Busboy_comparison-fastify-busboy-Node_20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"runtimeVersion": "20.9.0, V8 11.3.244.8-node.16",
"benchmarkName": "Busboy comparison",
"benchmarkEntryName": "fastify-busboy",
"benchmarkCycles": 500,
"benchmarkCycleSamples": 50,
"warmupCycles": 50,
"meanTimeNs": 188173.65372222223,
"meanTimeMs": 0.18817365372222222
}
10 changes: 10 additions & 0 deletions benchmarks/_results/Busboy_comparison-multipasta-Node_20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"runtimeVersion": "20.9.0, V8 11.3.244.8-node.16",
"benchmarkName": "Busboy comparison",
"benchmarkEntryName": "multipasta",
"benchmarkCycles": 500,
"benchmarkCycleSamples": 50,
"warmupCycles": 50,
"meanTimeNs": 67089.49805620349,
"meanTimeMs": 0.0670894980562035
}
7 changes: 7 additions & 0 deletions benchmarks/_results/results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
| Node | Option | Msecs/op | Ops/sec | V8 |
| ------ | -------------- | -------------- | --------- | --------------------- |
| 20.9.0 | multipasta | 0.067089 msecs | 14905.463 | V8 11.3.244.8-node.16 |
| 20.9.0 | fastify-busboy | 0.188174 msecs | 5314.240 | V8 11.3.244.8-node.16 |
| 20.9.0 | busboy | 0.259790 msecs | 3849.266 | V8 11.3.244.8-node.16 |

**Specs**: Core™ i9-9880H (2.3 GHz)
21 changes: 11 additions & 10 deletions benchmarks/busboy/contestants/busboy.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
'use strict'

const Busboy = require('busboy')
const { buffer, boundary } = require('../data')
const { buffers, boundary } = require('../data')

function process () {
const busboy = Busboy({
headers: {
'content-type': 'multipart/form-data; boundary=' + boundary
}
})
let processedData = ''
let processedSize = 0
let partCount = 0

return new Promise((resolve, reject) => {
busboy.on('file', (field, file, filename, encoding, mimetype) => {
// console.log('read file')
partCount++
file.on('data', (data) => {
processedData += data.toString()
// console.log(`File [${filename}] got ${data.length} bytes`);
})
file.on('end', (fieldname) => {
// console.log(`File [${fieldname}] Finished`);
processedSize += data.length
})
})
busboy.on('field', (field, value) => {
processedSize += value.length
partCount++
})

busboy.on('error', function (err) {
reject(err)
})
busboy.on('finish', function () {
resolve(processedData)
resolve([processedSize, partCount])
})
busboy.write(buffer, () => { })
for (const buffer of buffers) { busboy.write(buffer, () => { }) }

busboy.end()
})
Expand Down
22 changes: 12 additions & 10 deletions benchmarks/busboy/contestants/fastify-busboy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Busboy = require('../../../lib/main')
const { buffer, boundary } = require('../data')
const { buffers, boundary } = require('../data')

function process () {
const busboy = new Busboy({
Expand All @@ -10,27 +10,29 @@ function process () {
}
})

let processedData = ''
let processedSize = 0
let partCount = 0

return new Promise((resolve, reject) => {
busboy.on('file', (field, file, filename, encoding, mimetype) => {
// console.log('read file')
partCount++
file.on('data', (data) => {
processedData += data.toString()
// console.log(`File [${filename}] got ${data.length} bytes`);
})
file.on('end', (fieldname) => {
// console.log(`File [${fieldname}] Finished`);
processedSize += data.length
})
})
busboy.on('field', (field, value) => {
processedSize += value.length
partCount++
})

busboy.on('error', function (err) {
reject(err)
})
busboy.on('finish', function () {
resolve(processedData)
resolve([processedSize, partCount])
})
busboy.write(buffer, () => { })

for (const buffer of buffers) { busboy.write(buffer, () => { }) }

busboy.end()
})
Expand Down
40 changes: 40 additions & 0 deletions benchmarks/busboy/contestants/multipasta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict'

const MP = require('multipasta')
const { buffers, boundary } = require('../data')

function process () {
return new Promise((resolve, reject) => {
let processedSize = 0
let partCount = 0
const parser = MP.make({
headers: {
'content-type': 'multipart/form-data; boundary=' + boundary
},
onField (_info, value) {
processedSize += value.length
partCount++
},
onFile (_info) {
partCount++
return function (chunk) {
if (chunk !== null) {
processedSize += chunk.length
}
}
},
onError (err) {
reject(err)
},
onDone () {
resolve([processedSize, partCount])
}
})
for (const buffer of buffers) { parser.write(buffer) }
parser.end()
})
}

module.exports = {
process
}
45 changes: 35 additions & 10 deletions benchmarks/busboy/data.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
'use strict'

const boundary = '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k'
const randomContent = Buffer.from(makeString(1024 * 500), 'utf8')
const buffer = createMultipartBuffer(boundary)
const fileContent = Buffer.from(makeString(1024 * 512), 'utf8')
const fileCount = 2
const fieldContent = Buffer.from(makeString(128), 'utf8')
const fieldCount = 10
const chunkSize = 16000

const buffers = createMultipartBuffer(boundary)

function makeString (length) {
let result = ''
Expand All @@ -17,18 +22,38 @@ function makeString (length) {

function createMultipartBuffer (boundary) {
const payload = [
'--' + boundary,
'Content-Disposition: form-data; name="upload_file_0"; filename="1k_a.dat"',
'Content-Type: application/octet-stream',
'',
randomContent,
/* eslint-disable no-array-constructor */
...Array.from({ length: fieldCount }, (_, i) => [
'--' + boundary,
`Content-Disposition: form-data; name="field_${i}"`,
'Content-Type: application/octet-stream',
'',
fieldContent
]).flat(),
/* eslint-disable no-array-constructor */
...Array.from({ length: fileCount }, (_, i) => [
'--' + boundary,
`Content-Disposition: form-data; name="file_${i}"; filename="file.dat"`,
'Content-Type: application/octet-stream',
'',
fileContent
]).flat(),
'--' + boundary + '--'
].join('\r\n')
return Buffer.from(payload, 'ascii')
const buf = Buffer.from(payload, 'ascii')
// split into 16000 byte chunks to simulate network packets
const buffers = []
for (let i = 0; i < buf.length; i += chunkSize) {
buffers.push(buf.subarray(i, i + chunkSize))
}
return buffers
}

module.exports = {
boundary,
buffer,
randomContent
buffers,
fileContent,
fileCount,
fieldContent,
fieldCount
}
16 changes: 14 additions & 2 deletions benchmarks/busboy/executioner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

const { process: processBusboy } = require('./contestants/busboy')
const { process: processFastify } = require('./contestants/fastify-busboy')
const { process: processMultipasta } = require('./contestants/multipasta')
const { getCommonBuilder } = require('../common/commonBuilder')
const { validateAccuracy } = require('./validator')
const { resolveContestant } = require('../common/contestantResolver')
const { outputResults } = require('../common/resultUtils')

const contestants = {
busboy: measureBusboy,
fastify: measureFastify
fastify: measureFastify,
multipasta: measureMultipasta
}

async function measureBusboy () {
Expand All @@ -32,6 +34,16 @@ async function measureFastify () {
outputResults(benchmark, benchmarkResults)
}

async function measureMultipasta () {
const benchmark = getCommonBuilder()
.benchmarkName('Busboy comparison')
.benchmarkEntryName('multipasta')
.asyncFunctionUnderTest(processMultipasta)
.build()
const benchmarkResults = await benchmark.executeAsync()
outputResults(benchmark, benchmarkResults)
}

function execute () {
return validateAccuracy(processBusboy())
.then(() => {
Expand All @@ -43,7 +55,7 @@ function execute () {
}).then(() => {
console.log('all done')
}).catch((err) => {
console.error(`Something went wrong: ${err.message}`)
console.error('Something went wrong', err)
})
}

Expand Down
7 changes: 4 additions & 3 deletions benchmarks/busboy/validator.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use strict'

const { validateEqual } = require('validation-utils')
const { randomContent } = require('./data')
const { fileContent, fileCount, fieldContent, fieldCount } = require('./data')

const EXPECTED_RESULT = randomContent.toString()
const EXPECTED_RESULT = (fileContent.length * fileCount) + (fieldContent.length * fieldCount)

async function validateAccuracy (actualResultPromise) {
const result = await actualResultPromise
const [result, parts] = await actualResultPromise
validateEqual(result, EXPECTED_RESULT)
validateEqual(parts, fileCount + fieldCount)
}

module.exports = {
Expand Down
20 changes: 8 additions & 12 deletions benchmarks/common/commonBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,28 @@ const options = getopts(process.argv.slice(1), {

const PRESET = {
LOW: (builder) => {
return builder
.warmupCycles(1000)
.benchmarkCycles(1000)
return builder.warmupCycles(5).benchmarkCycles(50)
},

MEDIUM: (builder) => {
return builder
.warmupCycles(1000)
.benchmarkCycles(2000)
return builder.warmupCycles(10).benchmarkCycles(100)
},

HIGH: (builder) => {
return builder
.warmupCycles(1000)
.benchmarkCycles(10000)
return builder.warmupCycles(50).benchmarkCycles(500)
}
}

function getCommonBuilder () {
const presetId = options.preset || 'MEDIUM'
const preset = validateNotNil(PRESET[presetId.toUpperCase()], `Unknown preset: ${presetId}`)
const preset = validateNotNil(
PRESET[presetId.toUpperCase()],
`Unknown preset: ${presetId}`
)

const builder = new BenchmarkBuilder()
preset(builder)
return builder
.benchmarkCycleSamples(50)
return builder.benchmarkCycleSamples(50)
}

module.exports = {
Expand Down
7 changes: 4 additions & 3 deletions benchmarks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
"install-node": "nvm install 17.2.0 && nvm install 16.13.1 && nvm install 14.18.2 && nvm install 12.22.7",
"benchmark-busboy": "node busboy/executioner.js -c 0",
"benchmark-fastify": "node busboy/executioner.js -c 1",
"benchmark-all": "npm run benchmark-busboy -- -p high && npm run benchmark-fastify -- -p high",
"benchmark-all-medium": "npm run benchmark-busboy -- -p medium && npm run benchmark-fastify -- -p medium",
"benchmark-all-low": "npm run benchmark-busboy -- -p low && npm run benchmark-fastify -- -p low",
"benchmark-multipasta": "node busboy/executioner.js -c 2",
"benchmark-all": "npm run benchmark-busboy -- -p high && npm run benchmark-fastify -- -p high && npm run benchmark-multipasta -- -p high",
"benchmark-all-medium": "npm run benchmark-busboy -- -p medium && npm run benchmark-fastify -- -p medium && npm run benchmark-multipasta -- -p medium",
"benchmark-all-low": "npm run benchmark-busboy -- -p low && npm run benchmark-fastify -- -p low && npm run benchmark-multipasta -- -p low",
"combine-results": "node common/resultsCombinator.js -r _results -p 6"
}
}
Loading