Skip to content
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

Memory leak #4264

Closed
berge616 opened this issue Dec 15, 2017 · 27 comments
Closed

Memory leak #4264

berge616 opened this issue Dec 15, 2017 · 27 comments
Labels
performance Related to a potential performance optimization

Comments

@berge616
Copy link

berge616 commented Dec 15, 2017

Sails version:1.0.0-12
Node version:8.9.3
NPM version:5.5.1
DB adapter name: sails-mysql
DB adapter version: 1.0.0-15
Operating system:na


https://github.com/node-machine/machine/issues/46

--Copied below:

screen shot 2017-12-16 at 2 35 10 pm

There is a memory leak in this module when called through sails-mysql. The above image shows the memory leak on a system with 768mb ram. The ECS container gets kicked when it reaches its max so that's why the sawtooth. This is a low use system so this memory leak is quite significant. Reproduced locally with a fresh sails project and took heap snapshots before any calls and then after running many calls through the api. Compared these heaps in chromes profiling and found an alarming number of debug closures being left in memory(both snapshots were taken immediately after forcing a garbage collection)

screen shot 2017-12-15 at 11 03 00 am

This is easily reproducible by installing sails v1 and connecting it to a mysql db with some basic routes to add a record to the db.

Here is the code i used to get heap size and generate the snapshots:

npm install heapdump
const heapdump = require('heapdump');

 generateHeapDumpAndStats: function(req, res){
 //1. Force garbage collection every time this function is called
 try {
   global.gc();
 } catch (e) {
   console.log("You must run program with 'node --expose-gc index.js' or 'npm start'");
   process.exit();
 }

 //2. Output Heap stats
 var heapUsed = process.memoryUsage().heapUsed;
 console.log("Program is using " + heapUsed + " bytes of Heap.")
    res.status(200).json({heapUsed:heapUsed/1042/1024});

 //3. Get Heap dump
 //process.kill(process.pid, 'SIGUSR2');
    heapdump.writeSnapshot();
   }

These lines seem to be the culprit:

https://github.com/node-machine/machine/blob/13.0/lib/private/intercept-exit-callbacks.js#L260-L261
https://github.com/node-machine/machine/blob/13.0/lib/private/help-exec-machine-instance.js#L108-L110

I'm using the following versions:

    "sails": "^1.0.0-42",
    "sails-disk": "^1.0.0-12",
    "sails-hook-custom-blueprints": "^1.0.0",
    "sails-hook-grunt": "^3.0.0",
    "sails-hook-orm": "^2.0.0-22",
    "sails-mysql": "^1.0.0-15",
@sailsbot
Copy link

Hi @berge616! It looks like you missed a step or two when you created your issue. Please edit your comment (use the pencil icon at the top-right corner of the comment box) and fix the following:

  • Provide your Sails version
  • Provide your Node version
  • Provide your NPM version
  • Provide your Operating system

As soon as those items are rectified, post a new comment (e.g. “Ok, fixed!”) below and we'll take a look. Thanks!

*If you feel this message is in error, or you want to debate the merits of my existence (sniffle), please contact inquiries@sailsjs.com

@berge616
Copy link
Author

fixed

@sailsbot
Copy link

@berge616 Thanks for posting, we'll take a look as soon as possible.


For help with questions about Sails, click here. If you’re interested in hiring @sailsbot and her minions in Austin, click here.

@sgress454
Copy link
Member

Original thread from Gitter: https://gitter.im/balderdashy/sails?at=5a32e1a1a2be466828a140c6

Kyle will try commenting out those debugs and seeing if it fixes the issue...

@berge616
Copy link
Author

Commented out those debug lines along with similiar ones in identically named files from machinepack-mysql and the leak is fixed. Confirmed by observing dumps after removal of Debug lines

@sgress454
Copy link
Member

Thanks @berge616!

@sgress454
Copy link
Member

@mikermcneil
Copy link
Member

mikermcneil commented Dec 17, 2017

@berge616 @sgress454 thanks! And @sgress454 that plan in Trello sounds good, though in the latest runner, we're not actually using the debug package, so it won't affect us there.

@berge616 For the mp-mysql stuff, assuming this is about the query logs, just to make sure: Were you using NODE_ENV=production when you tested this? I took a look at potential issues from debug but didn't find anything particularly telling. We definitely want to keep query logging though, so worst case we can just add an if (process.env.DEBUG) {…} check around the relevant calls to debug(). That should isolate the problem so that it only temporarily affects apps while native query logging is enabled. (That said, if we've isolated it to that point, we might as well try updating debug and, if this hasn't been fixed there yet, try to do a patch in that package)

@sgress454
Copy link
Member

@mikermcneil These are debug calls inside of machine runner (see line numbers in original post), and they're made regardless of environment (they just don't actually output anything if you don't set the DEBUG env var). So the issue seems to be that a new debug instance is made on every run, where typically we just create a single instance when we first require debug. I think it's done that way so that the debugs can be namespaced to the specific machine that's running. They should get cleaned up anyway, but at least in @berge616's test they seem to linger indefinitely. If he comments out those lines, the memory issue goes away.

@sgress454
Copy link
Member

@berge616
Copy link
Author

@mikermcneil yes this is with the env set to production. They for sure linger forever. Spin up a new sails project with mysql db and hit it with a load test. You'll see the memory grow indefinitely even with GC running. Each debug stmt takes up ~300 bytes and with each api call calling the db a handful of times, this adds up pretty quick.

mikermcneil added a commit to balderdashy/sails-mysql that referenced this issue Dec 19, 2017
mikermcneil added a commit to sailshq/machinepack-mysql that referenced this issue Dec 19, 2017
@mikermcneil
Copy link
Member

mikermcneil commented Dec 19, 2017

@berge616 @sgress454 just pushed up experimental upgrades to mp-mysql and sails-mysql in balderdashy/sails-mysql@075d759 and sailshq/machinepack-mysql@d9d31aa

To test:

  • from inside mp-mysql, run git pull && rm -rf node_modules && rm package-lock.json && npm install && npm link
  • from inside sails-mysql, run git pull && rm -rf node_modules && rm package-lock.json && npm install && npm link && npm link machinepack-mysql
  • from inside a test Sails app, run rm -rf node_modules && rm package-lock.json && npm link sails-mysql
  • then try it out (should be no leaks)

@berge616
Copy link
Author

berge616 commented Dec 19, 2017

@mikermcneil are there any breaking changes for this newer version? I'm getting this error when I try it out:

{ UsageError: Sorry, `.exec()` doesn't know how to handle {...} callbacks.
Please provide a callback function when calling .exec().
|  If you passed in {...} on purpose as a "switchback" (dictionary of callbacks),
|  then try calling .switch() intead of .exec().
 [?] See https://sailsjs.com/support for more help.

@mikermcneil
Copy link
Member

mikermcneil commented Dec 20, 2017

@berge616 there are! Thanks for pointing that out-- I should have caught it. Pushed sailshq/machinepack-mysql@8660bf0 and balderdashy/sails-mysql@5e8ed7e

Caveat: I thought I'd nabbed them all the first time when I took care of example->outputExample, etc, but I haven't had time to go much past quickly running a couple of tests yet, so it'd be great to hear if you see any other compatibility issues trying it out in practice with the repos linked

@mikermcneil mikermcneil added the performance Related to a potential performance optimization label Dec 20, 2017
@berge616
Copy link
Author

@mikermcneil Thanks for fixing that. The debug() memory leak is gone! I ran through all my tests and everything looks good. Any timeline for getting this released?

@mikermcneil
Copy link
Member

@berge616 awesome! Thanks for checking. It'll technically be a breaking change to mp-mysql, so I went ahead and published 3.0.0 of that. I'll try pointing sails-mysql at it to make sure all the tests pass. Assuming that looks good, ready whenever

mikermcneil added a commit to balderdashy/sails-mysql that referenced this issue Dec 20, 2017
@mikermcneil
Copy link
Member

@mikermcneil
Copy link
Member

mikermcneil commented Dec 20, 2017

LGTM - published sails-mysql@1.0.0-16 (please give that a shot and let me know if you run into any issues!)

@berge616
Copy link
Author

screen shot 2017-12-21 at 3 00 23 pm

Everything looks good to me!

@itomas
Copy link

itomas commented Dec 22, 2017

After 1.0.0-16 sendNativeQuery is not working. https://next.sailsjs.com/documentation/reference/waterline-orm/datastores/send-native-query

Promise never resolves.

@max918
Copy link

max918 commented Dec 22, 2017

Hi, i am also focusing on this memory leak issue.
After update to sails-mysql@1.0.0-16, the transaction method not work.
I just created empty template sails and testing controller endpoint like this:

transaction: function(req, res) {
sails.log.debug('start');
sails.getDatastore().transaction(function(db, proceed) {
return proceed();
}).exec(function(err) {
sails.log.debug('end');
return res.ok();
})
}

on sails-mysql@1.0.0-15, it print "start" and "end" correctly.
but on sails-mysql@1.0.0-16, it only print "start"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Related to a potential performance optimization
Development

No branches or pull requests

9 participants