Skip to content

Commit d4ce0b1

Browse files
authored
perf: improve perf of parseRawHeaders (#2781)
1 parent 71c1f20 commit d4ce0b1

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

benchmarks/parseRawHeaders.mjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { bench, group, run } from 'mitata'
2+
import { parseRawHeaders } from '../lib/core/util.js'
3+
4+
const rawHeadersMixed = ['key', 'value', Buffer.from('key'), Buffer.from('value')]
5+
const rawHeadersOnlyStrings = ['key', 'value', 'key', 'value']
6+
const rawHeadersOnlyBuffers = [Buffer.from('key'), Buffer.from('value'), Buffer.from('key'), Buffer.from('value')]
7+
const rawHeadersContent = ['content-length', 'value', 'content-disposition', 'form-data; name="fieldName"']
8+
9+
group('parseRawHeaders', () => {
10+
bench('only strings', () => {
11+
parseRawHeaders(rawHeadersOnlyStrings)
12+
})
13+
bench('only buffers', () => {
14+
parseRawHeaders(rawHeadersOnlyBuffers)
15+
})
16+
bench('mixed', () => {
17+
parseRawHeaders(rawHeadersMixed)
18+
})
19+
bench('content-disposition special case', () => {
20+
parseRawHeaders(rawHeadersContent)
21+
})
22+
})
23+
24+
await run()

lib/core/util.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -279,22 +279,30 @@ function parseHeaders (headers, obj) {
279279
}
280280

281281
function parseRawHeaders (headers) {
282-
const ret = []
282+
const len = headers.length
283+
const ret = new Array(len)
284+
283285
let hasContentLength = false
284286
let contentDispositionIdx = -1
287+
let key
288+
let val
289+
let kLen = 0
285290

286291
for (let n = 0; n < headers.length; n += 2) {
287-
const key = headers[n + 0].toString()
288-
const val = headers[n + 1].toString('utf8')
292+
key = headers[n]
293+
val = headers[n + 1]
294+
295+
typeof key !== 'string' && (key = key.toString())
296+
typeof val !== 'string' && (val = val.toString('utf8'))
289297

290-
if (key.length === 14 && (key === 'content-length' || key.toLowerCase() === 'content-length')) {
291-
ret.push(key, val)
298+
kLen = key.length
299+
if (kLen === 14 && key[7] === '-' && (key === 'content-length' || key.toLowerCase() === 'content-length')) {
292300
hasContentLength = true
293-
} else if (key.length === 19 && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) {
294-
contentDispositionIdx = ret.push(key, val) - 1
295-
} else {
296-
ret.push(key, val)
301+
} else if (kLen === 19 && key[7] === '-' && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) {
302+
contentDispositionIdx = n + 1
297303
}
304+
ret[n] = key
305+
ret[n + 1] = val
298306
}
299307

300308
// See https://github.com/nodejs/node/pull/46528

test/node-test/util.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ test('parseHeaders', () => {
8989

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

9495
test('buildURL', () => {

0 commit comments

Comments
 (0)