Skip to content

Commit b345c18

Browse files
committed
perf(tree): reduce overhead of built TernarySearchTree
1 parent 95bd929 commit b345c18

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

lib/core/tree.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,19 @@ class TstNode {
1717
/** @type {number} */
1818
code
1919
/**
20-
* @param {Uint8Array} key
20+
* @param {string} key
2121
* @param {any} value
2222
* @param {number} index
2323
*/
2424
constructor (key, value, index) {
2525
if (index === undefined || index >= key.length) {
2626
throw new TypeError('Unreachable')
2727
}
28-
this.code = key[index]
28+
const code = this.code = key.charCodeAt(index)
29+
// check code is ascii string
30+
if (code > 0x7F) {
31+
throw new TypeError('key must be ascii string')
32+
}
2933
if (key.length !== ++index) {
3034
this.middle = new TstNode(key, value, index)
3135
} else {
@@ -34,7 +38,7 @@ class TstNode {
3438
}
3539

3640
/**
37-
* @param {Uint8Array} key
41+
* @param {string} key
3842
* @param {any} value
3943
*/
4044
add (key, value) {
@@ -45,7 +49,11 @@ class TstNode {
4549
let index = 0
4650
let node = this
4751
while (true) {
48-
const code = key[index]
52+
const code = key.charCodeAt(index)
53+
// check code is ascii string
54+
if (code > 0x7F) {
55+
throw new TypeError('key must be ascii string')
56+
}
4957
if (node.code === code) {
5058
if (length === ++index) {
5159
node.value = value
@@ -111,7 +119,7 @@ class TernarySearchTree {
111119
node = null
112120

113121
/**
114-
* @param {Uint8Array} key
122+
* @param {string} key
115123
* @param {any} value
116124
* */
117125
insert (key, value) {
@@ -135,7 +143,7 @@ const tree = new TernarySearchTree()
135143

136144
for (let i = 0; i < wellknownHeaderNames.length; ++i) {
137145
const key = headerNameLowerCasedRecord[wellknownHeaderNames[i]]
138-
tree.insert(Buffer.from(key), key)
146+
tree.insert(key, key)
139147
}
140148

141149
module.exports = {

test/node-test/tree.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,34 @@ const assert = require('node:assert')
77

88
describe('Ternary Search Tree', () => {
99
test('The empty key cannot be added.', () => {
10-
assert.throws(() => new TernarySearchTree().insert(Buffer.from(''), ''))
10+
assert.throws(() => new TernarySearchTree().insert('', ''))
1111
const tst = new TernarySearchTree()
12-
tst.insert(Buffer.from('a'), 'a')
13-
assert.throws(() => tst.insert(Buffer.from(''), ''))
12+
tst.insert('a', 'a')
13+
assert.throws(() => tst.insert('', ''))
1414
})
1515

1616
test('looking up not inserted key returns null', () => {
17-
assert.throws(() => new TernarySearchTree().insert(Buffer.from(''), ''))
1817
const tst = new TernarySearchTree()
19-
tst.insert(Buffer.from('a'), 'a')
18+
tst.insert('a', 'a')
2019
assert.strictEqual(tst.lookup(Buffer.from('non-existant')), null)
2120
})
2221

22+
test('not ascii string', () => {
23+
assert.throws(() => new TernarySearchTree().insert('\x80', 'a'))
24+
const tst = new TernarySearchTree()
25+
tst.insert('a', 'a')
26+
// throw on TstNode
27+
assert.throws(() => tst.insert('a\x80', 'a'))
28+
})
29+
2330
test('duplicate key', () => {
2431
const tst = new TernarySearchTree()
25-
const key = Buffer.from('a')
32+
const key = 'a'
33+
const lookupKey = Buffer.from(key)
2634
tst.insert(key, 'a')
27-
assert.strictEqual(tst.lookup(key), 'a')
35+
assert.strictEqual(tst.lookup(lookupKey), 'a')
2836
tst.insert(key, 'b')
29-
assert.strictEqual(tst.lookup(key), 'b')
37+
assert.strictEqual(tst.lookup(lookupKey), 'b')
3038
})
3139

3240
test('tree', () => {
@@ -59,7 +67,7 @@ describe('Ternary Search Tree', () => {
5967
const key = generateAsciiString((Math.random() * 100 + 5) | 0)
6068
const lowerCasedKey = random[i] = key.toLowerCase()
6169
randomBuffer[i] = Buffer.from(key)
62-
tst.insert(Buffer.from(lowerCasedKey), lowerCasedKey)
70+
tst.insert(lowerCasedKey, lowerCasedKey)
6371
}
6472

6573
for (let i = 0; i < LENGTH; ++i) {

0 commit comments

Comments
 (0)