websockets / ws

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js
MIT License
21.73k stars 2.42k forks source link

Memory leak #1889

Closed ghost closed 3 years ago

ghost commented 3 years ago

Description

close and terminate do not always free the memory Garbage collection is completely performed only after a few minutes after ws is closed and terminated (even with force garbage collection)

Reproducible in:

Steps to reproduce:

  1. Create file
    
    const WebSocket = require('ws')
    const restify = require('restify')

const server = restify.createServer()

server.get('/', async (req, res, next) => { const ws = new WebSocket('wss://api.bitfinex.com/ws/')

ws.on('error', () => {}) setTimeout(() => { ws.close() ws.terminate() }, 1000) res.send() next() })

server.listen(3000)



2. Install `autocannon` and `restify`

3. Run `node --inspect basic.js`

4. Open `Memory` tab in DevTools - Node.js and create snapshot

5. Run `autocannon -c 2 localhost:3000` in the different terminal

6. wait a couple of minutes for GC to clear the memory

7.  Create snapshot

#### Expected result:

Latest snapshot should display the same amount of memory as in step 4

#### Actual result:

Latest snapshot displays about 15-20MB

<!-- e.g. What actually happened -->

#### Attachments:

![image](https://user-images.githubusercontent.com/70510980/119353627-caa25d80-bcab-11eb-83d0-1bab86324cd3.png)

UPD: https://github.com/websockets/ws/issues/1889#issuecomment-847645125
lpinca commented 3 years ago

I'm on Node.js 16.2.0 and macOS but I can't reproduce. Ran autocannon after every snapshot and waited ~4 min before taking the snapshots.

Screen Shot 2021-05-24 at 20 32 16 Screen Shot 2021-05-24 at 20 32 40 Screen Shot 2021-05-24 at 20 33 09
ghost commented 3 years ago

Indeed, if we wait longer, the memory is cleared (for example, after 3.5 minutes on the screenshot below), but not always completely

image

after 6 minutes some closures remained in memory (possibly related only to 'restify')

image

The remaining question: why Garbage collector cannot clean up memory in a shorter time ("Garbage ollect" button doesn't help)

lpinca commented 3 years ago

I think because there is plenty of memory available so it does not aggressively try to reclaim memory.

ghost commented 3 years ago

but it should clear the memory immediately when you click on the "Collect garbage" button, isn't?

lpinca commented 3 years ago

I don't know. You can try forcing garbage collection with global.gc() and using the --max-old-space option. Garbage collectors are scary beasts.

lpinca commented 3 years ago

I'm closing this as it does not seem to be an issue in ws. Discussion can continue if needed.