Skip to content

Commit 311a471

Browse files
Uzlopaktsctx
authored andcommitted
perf: improve TernarySearchTree (nodejs#2782)
Co-authored-by: tsctx <[email protected]>
1 parent 9ed779f commit 311a471

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

benchmarks/TernarySearchTree.mjs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { bench, group, run } from 'mitata'
2+
import { tree } from '../lib/core/tree.js'
3+
4+
const contentLength = Buffer.from('Content-Length')
5+
const contentLengthUpperCase = Buffer.from('Content-Length'.toUpperCase())
6+
const contentLengthLowerCase = Buffer.from('Content-Length'.toLowerCase())
7+
8+
group('tree.search', () => {
9+
bench('content-length', () => {
10+
tree.lookup(contentLengthLowerCase)
11+
})
12+
bench('CONTENT-LENGTH', () => {
13+
tree.lookup(contentLengthUpperCase)
14+
})
15+
bench('Content-Length', () => {
16+
tree.lookup(contentLength)
17+
})
18+
})
19+
20+
await run()

lib/core/tree.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ class TstNode {
8383
while (node !== null && index < keylength) {
8484
let code = key[index]
8585
// A-Z
86-
if (code >= 0x41 && code <= 0x5a) {
86+
// First check if it is bigger than 0x5a.
87+
// Lowercase letters have higher char codes than uppercase ones.
88+
// Also we assume that headers will mostly contain lowercase characters.
89+
if (code <= 0x5a && code >= 0x41) {
8790
// Lowercase for uppercase.
8891
code |= 32
8992
}
@@ -121,6 +124,7 @@ class TernarySearchTree {
121124

122125
/**
123126
* @param {Uint8Array} key
127+
* @return {any}
124128
*/
125129
lookup (key) {
126130
return this.node?.search(key)?.value ?? null

test/node-test/tree.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ describe('Ternary Search Tree', () => {
1313
assert.throws(() => tst.insert(Buffer.from(''), ''))
1414
})
1515

16+
test('looking up not inserted key returns null', () => {
17+
assert.throws(() => new TernarySearchTree().insert(Buffer.from(''), ''))
18+
const tst = new TernarySearchTree()
19+
tst.insert(Buffer.from('a'), 'a')
20+
assert.strictEqual(tst.lookup(Buffer.from('non-existant')), null)
21+
})
22+
1623
test('duplicate key', () => {
1724
const tst = new TernarySearchTree()
1825
const key = Buffer.from('a')

0 commit comments

Comments
 (0)