-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Socket.io memory leak when used with HTTPS/TLS server and Node 0.8.x #1177
Comments
Has this been fixed in node 0.9.22? |
Do you mean 0.8.22? I highly doubt it since it would require a big change in the way the |
It has not. I've got a production nodejs instances (0.10.1) restarting nightly due to memory leak of ssl+socket.io. I suspect it's related to all this. |
We got this to work well, finally. I think this change worked after all! Jake On Fri, Mar 29, 2013 at 3:53 PM, Jeff Minard [email protected]:
Jacob Beasley |
0.9.14 released with this patch. Thanks @jpallen |
Do we know what node versions this applies to? Does this apply to v0.10.22? |
We recently tried to upgrade our app to Node 0.8 from 0.6 and ran into a large
memory leak which we've traced back to socket.io. The fault really lies with how
Node 0.8 handles buffers in its TLS library, but Socket.io triggers the problem.
The problem is that Socket.io holds a reference to the
head
buffer which comesin on the
upgrade
event from the server (line 617 of lib/manager.js). Thisreference is held for the duration of the lifetime of the WebSocket connection.
This is a small buffer and so is not in itself responsible for the memory leak.
The trouble is that in Node.js 0.8, the TLS library allocates large
10Mb buffers which it thens allocates portions of to smaller buffers for incoming
requests. The
head
buffer passed to theupgrade
event is actually part of alarger 10Mb buffer. These 10Mb buffers are not freed by the garbage collector if
any of their child buffers are still in use, and so holding a reference to the
small
head
buffer is actually keeping a much larger 10Mb buffer frombeing freed when socket.io is used with the HTTPS server.
Some Data
I've created a small test script which can found in the
https://github.com/jpallen/socket.io-memory-test repository (also included below).
This starts a
simple HTTPS and WebSocket server that listens for incoming
connections but does nothing with them. Every second a new socket.io client
connects to the WebSocket server, and every quarter of a second a 265Kb image
is uploaded to the HTTPS server. The image upload ensures that plenty of
10Mb buffers are created, and the continual stream of WebSocket connections
ensures that there are plenty of references to the req.head buffer which hold on
to these 10Mb buffers. The test script can be run with only uploads, only
websockets or both. The results are quite clear:
Neither WebSocket connections nor the uploads are a problem themselves and allow
the garbage collector to do its job. Together however there is a significant
memory leak.
Fix
The fix is simple.
req.head
is only used by thewebsockets/default.js
transport and it is safe to discard it once this has established the connection.
We can do this almost immediately in lib/manager.js:
With this patch applied, the combination of WebSockets and an HTTPS behaves how
one would expect:
The memory usage with WebSockets and uploads together now looks like the
supposition of the two individually. (The scale is much
smaller on this graph compared to the leaking example above.)
Remarks
I'm going to create an issue for Node.js about this as well. I think this is a design
flaw in the way Node 0.8 handles buffers in the TLS library since holding on to a
small buffer like
head
for an extended period of time should not have such a dramaticeffect for the rest of the app.
The TLS server in Node 0.6 doesn't allocate buffers in large 10Mb chunks and so
is unaffected by this memory leak. Here is an example run for Node 0.6 if you're
interested:
The graph is less linear because we don't have control over garbage collecting.
Note again the smaller scale compared to the leaking example.
Test Script
You need an file called
image.png
in the same directory as this script.Usage
A more complete test suite can found in jpallen/socket.io-memory-test from my
various experiments.
The text was updated successfully, but these errors were encountered: