Skip to content

Commit

Permalink
perf: improve perf of parseRawHeaders (nodejs#2781)
Browse files Browse the repository at this point in the history
  • Loading branch information
Uzlopak committed Feb 19, 2024
1 parent 1a26357 commit 4ca5ea9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
24 changes: 24 additions & 0 deletions benchmarks/parseRawHeaders.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { bench, group, run } from 'mitata'
import { parseRawHeaders } from '../lib/core/util.js'

const rawHeadersMixed = ['key', 'value', Buffer.from('key'), Buffer.from('value')]
const rawHeadersOnlyStrings = ['key', 'value', 'key', 'value']
const rawHeadersOnlyBuffers = [Buffer.from('key'), Buffer.from('value'), Buffer.from('key'), Buffer.from('value')]
const rawHeadersContent = ['content-length', 'value', 'content-disposition', 'form-data; name="fieldName"']

group('parseRawHeaders', () => {
bench('only strings', () => {
parseRawHeaders(rawHeadersOnlyStrings)
})
bench('only buffers', () => {
parseRawHeaders(rawHeadersOnlyBuffers)
})
bench('mixed', () => {
parseRawHeaders(rawHeadersMixed)
})
bench('content-disposition special case', () => {
parseRawHeaders(rawHeadersContent)
})
})

await run()
26 changes: 17 additions & 9 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,22 +279,30 @@ function parseHeaders (headers, obj) {
}

function parseRawHeaders (headers) {
const ret = []
const len = headers.length
const ret = new Array(len)

let hasContentLength = false
let contentDispositionIdx = -1
let key
let val
let kLen = 0

for (let n = 0; n < headers.length; n += 2) {
const key = headers[n + 0].toString()
const val = headers[n + 1].toString('utf8')
key = headers[n]
val = headers[n + 1]

typeof key !== 'string' && (key = key.toString())
typeof val !== 'string' && (val = val.toString('utf8'))

if (key.length === 14 && (key === 'content-length' || key.toLowerCase() === 'content-length')) {
ret.push(key, val)
kLen = key.length
if (kLen === 14 && key[7] === '-' && (key === 'content-length' || key.toLowerCase() === 'content-length')) {
hasContentLength = true
} else if (key.length === 19 && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) {
contentDispositionIdx = ret.push(key, val) - 1
} else {
ret.push(key, val)
} else if (kLen === 19 && key[7] === '-' && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) {
contentDispositionIdx = n + 1
}
ret[n] = key
ret[n + 1] = val
}

// See https://github.com/nodejs/node/pull/46528
Expand Down
1 change: 1 addition & 0 deletions test/node-test/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ test('parseHeaders', () => {

test('parseRawHeaders', () => {
assert.deepEqual(util.parseRawHeaders(['key', 'value', Buffer.from('key'), Buffer.from('value')]), ['key', 'value', 'key', 'value'])
assert.deepEqual(util.parseRawHeaders(['content-length', 'value', 'content-disposition', 'form-data; name="fieldName"']), ['content-length', 'value', 'content-disposition', 'form-data; name="fieldName"'])
})

test('buildURL', () => {
Expand Down

0 comments on commit 4ca5ea9

Please sign in to comment.