Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ msw-*.tgz
/examples
/test/modules/node/node-esm-tests
*.vitest-temp.json
*.heapprofile
18 changes: 18 additions & 0 deletions test/node/performance/generate-heapmap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { spawnSync } from 'node:child_process'

spawnSync('node', [new URL('./memory-usage.js', import.meta.url).pathname], {
stdio: 'inherit',
env: {
...process.env,
NODE_OPTIONS: `--expose-gc --heap-prof --heap-prof-dir=${new URL('.', import.meta.url).pathname} --heap-prof-name=${Date.now()}-msw.heapprofile`,
},
})

spawnSync('node', [new URL('./memory-usage.js', import.meta.url).pathname], {
stdio: 'inherit',
env: {
...process.env,
USE_NODE: 1,
NODE_OPTIONS: `--expose-gc --heap-prof --heap-prof-dir=${new URL('.', import.meta.url).pathname} --heap-prof-name=${Date.now()}-node.heapprofile`,
},
})
40 changes: 40 additions & 0 deletions test/node/performance/memory-usage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import http from 'node:http'
import { setupServer } from 'msw/node'

async function profile() {
const startMemoryUsage = process.memoryUsage().heapUsed

for (let i = 0; i < 10_000; i++) {
let server

if (!process.env.USE_NODE) {
server = setupServer()
server.listen({ onUnhandledRequest: 'bypass' })
}

await new Promise((resolve) => {
http
.get('http://localhost/non-existent', () => resolve())
.on('error', () => resolve())
})

if (!process.env.USE_NODE) {
server.close()
}
}

const endMemoryUsage = process.memoryUsage().heapUsed
const memoryUsed = (endMemoryUsage - startMemoryUsage) / 1024 / 1024

console.log(
'Memory used:',
memoryUsed,
'MB',
process.env.USE_NODE ? '(Node.js)' : '(MSW)',
)

global.gc?.()
process.send?.(memoryUsed)
}

profile()
24 changes: 24 additions & 0 deletions test/node/performance/memory-usage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { spawn } from 'node:child_process'
import { DeferredPromise } from '@open-draft/deferred-promise'

it('does not leak memory when handling a large number of requests', async () => {

Check failure on line 4 in test/node/performance/memory-usage.test.ts

View workflow job for this annotation

GitHub Actions / publish

test/node/performance/memory-usage.test.ts > does not leak memory when handling a large number of requests

Error: Test timed out in 5000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ test/node/performance/memory-usage.test.ts:4:1

Check failure on line 4 in test/node/performance/memory-usage.test.ts

View workflow job for this annotation

GitHub Actions / publish

test/node/performance/memory-usage.test.ts > does not leak memory when handling a large number of requests

Error: Test timed out in 5000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ test/node/performance/memory-usage.test.ts:4:1

Check failure on line 4 in test/node/performance/memory-usage.test.ts

View workflow job for this annotation

GitHub Actions / test (node.js) (22)

test/node/performance/memory-usage.test.ts > does not leak memory when handling a large number of requests

Error: Test timed out in 5000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ test/node/performance/memory-usage.test.ts:4:1

Check failure on line 4 in test/node/performance/memory-usage.test.ts

View workflow job for this annotation

GitHub Actions / test (node.js) (20)

test/node/performance/memory-usage.test.ts > does not leak memory when handling a large number of requests

Error: Test timed out in 5000ms. If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout". ❯ test/node/performance/memory-usage.test.ts:4:1
// Spawn the memory consumption scenario in a child process
// so the test runner's memory consumption does not affect the results.
const child = spawn(
'node',
[new URL('./memory-usage.js', import.meta.url).pathname, '--expose-gc'],
{
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
},
)

const memoryUsedPromise = new DeferredPromise<number>()
child.on('message', (message) => {
if (typeof message === 'number') {
memoryUsedPromise.resolve(message)
}
})
const memoryUsed = await memoryUsedPromise

expect(memoryUsed).toBeLessThan(8)
})
Loading