joyent/node — Issue #2577: http client leaking memory in 0.6.7 (not 0.4.9)
Author: davepacheco
Created: 2012-01-18 23:06:51+00:00
State: open

I've got two node programs: (1) an end server that services HTTP requests, and (2) a "proxy" that receives HTTP requests and forwards them to the end server. With v0.4.9, both of these behave well under load. Under v0.6.7, the HTTP client uses a lot more memory, as measured by the OS RSS value. Leaving them running overnight results in requests that had been taking 40-50ms now taking upwards of several seconds.

Here's a graph comparing RSS between 0.4.9 and 0.6.7 under the same workload, which was an apachebench run:
https://skitch.com/dapsays/g2mj9/memory-usage

Here's the code I'm using:
https://gist.github.com/55d92fc6cf70e84bd154

As described in that gist, I've found that by adding a call to "subresponse.destroy()" to destroy the client HTTP response object in its "end" event handler, memory usage is much closer to normal (though still leaks a bit).

Without the subresponse.destroy() call, it looks like this:
https://skitch.com/dapsays/g37w5/node.js-0.6.7-memory-usage-without-fix-applied

With subresponse.destroy(), it looks like this:
https://skitch.com/dapsays/g37w6/node.js-memory-usage-with-subres

The workload is this:

# ab -c 100 -n 100000 http://10.99.99.24:8085/

And the actual numbers:
* With subresponse.destroy(): test.js went from 9.16-10.3MB before to 16.0 - 17.2MB after.
* Without subresponse.destroy(): test.js went from 9.16-11.4MB before to 61.8 - 64.1MB after.

I don't have the exact numbers from 0.4.9, but I wasn't seeing any leakage at all.

This is not likely heap fragmentation, since destroying the responses causes the memory to get cleaned up.