Skip to content

Commit 5ce4d25

Browse files
committed
fix: improve LRU cache with refresh-on-access and refactor benchmarks
- Add LRU refresh logic in sequential router to move accessed cache entries to the end, ensuring proper least-recently-used eviction - Extract duplicated benchmark code into reusable benchRouter function
1 parent 3947c64 commit 5ce4d25

2 files changed

Lines changed: 22 additions & 25 deletions

File tree

bench.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import httpPrevious from '0http-bun'
55
const silentErrorHandler = () =>
66
new Response('Internal Server Error', {status: 500})
77

8-
function setupRouter(router: IRouter) {
8+
function setupRouter(router: any) {
99
router.use((req: any, next: () => any) => {
1010
return next()
1111
})
@@ -21,6 +21,20 @@ function setupRouter(router: IRouter) {
2121
})
2222
}
2323

24+
function benchRouter(name: string, router: any) {
25+
group(name, () => {
26+
bench('Parameter URL', async () => {
27+
await router.fetch(new Request(new URL('http://localhost/0')))
28+
}).gc('inner')
29+
bench('Not Found URL', async () => {
30+
await router.fetch(new Request(new URL('http://localhost/0/404')))
31+
}).gc('inner')
32+
bench('Error URL', async () => {
33+
await router.fetch(new Request(new URL('http://localhost/0/error')))
34+
}).gc('inner')
35+
})
36+
}
37+
2438
const {router} = httpNext({errorHandler: silentErrorHandler})
2539
setupRouter(router)
2640

@@ -29,29 +43,8 @@ const {router: routerPrevious} = httpPrevious({
2943
})
3044
setupRouter(routerPrevious)
3145

32-
group('Next Router', () => {
33-
bench('Parameter URL', async () => {
34-
await router.fetch(new Request(new URL('http://localhost/0')))
35-
}).gc('inner')
36-
bench('Not Found URL', async () => {
37-
await router.fetch(new Request(new URL('http://localhost/0/404')))
38-
}).gc('inner')
39-
bench('Error URL', async () => {
40-
await router.fetch(new Request(new URL('http://localhost/0/error')))
41-
}).gc('inner')
42-
})
43-
44-
group('Previous Router', () => {
45-
bench('Parameter URL', async () => {
46-
await routerPrevious.fetch(new Request(new URL('http://localhost/0')))
47-
}).gc('inner')
48-
bench('Not Found URL', async () => {
49-
await routerPrevious.fetch(new Request(new URL('http://localhost/0/404')))
50-
}).gc('inner')
51-
bench('Error URL', async () => {
52-
await routerPrevious.fetch(new Request(new URL('http://localhost/0/error')))
53-
}).gc('inner')
54-
})
46+
benchRouter('Next Router', router)
47+
benchRouter('Previous Router', routerPrevious)
5548

5649
run({
5750
colors: true,

lib/router/sequential.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,15 @@ module.exports = (config = {}) => {
100100
if (match_result === undefined) {
101101
match_result = router.find(method, normalizedPath)
102102
methodCache.set(normalizedPath, match_result)
103-
// LRU-style eviction: remove oldest entry when cache exceeds max size
103+
// LRU eviction: remove oldest entry when cache exceeds max size
104104
if (methodCache.size > cacheSize) {
105105
const firstKey = methodCache.keys().next().value
106106
methodCache.delete(firstKey)
107107
}
108+
} else {
109+
// LRU refresh: move accessed entry to end so it's evicted last
110+
methodCache.delete(normalizedPath)
111+
methodCache.set(normalizedPath, match_result)
108112
}
109113
} else {
110114
match_result = router.find(method, normalizedPath)

0 commit comments

Comments
 (0)