Update 4 : by creating an instance of the restify client (see the /messages.js controllers) outside the function and calling global.gc () after each request, it seems that the memory growth rate was reduced by a lot (~ 500KB in 10 seconds). However, memory usage is still growing.
Update3 : came out through this post: https://journal.paul.querna.org/articles/2011/04/05/openssl-memory-use/
It may be worth noting that I am using HTTPS with Restify.
Update 2 . Updated code below current state. I tried reinstalling Restify with Express. Unfortunately, this did not matter. It seems that calling api at the end of the chain (restify -> mongodb -> external api) forces everything to be stored in memory.
Update 1 . I replaced Mongoose with the standard MongoDB driver. Memory usage seems to be growing faster, but the leak persists.
I have been working on this leak for a couple of days.
I use the APIs using Restify and Mongoose , and for every API call I do at least one MongoDB lookup. I have about 1-2 thousand users who get to the API several times a day.
What i tried
- I highlighted my code simply using Restify and used ApacheBench to run a huge number of requests (100k +). During the test, the memory usage is about 60 MB.
- I highlighted my code simply using Restify and Mongoose and tested it in the same way as described above. Memory usage is around 80 MB.
- I tested the full production code locally using ApacheBench. Memory usage is around 80 MB.
- I automatically dumped the heap at intervals. The biggest heap heap I had was 400 MB. All that I see is that there are many lines and arrays, but I cannot clearly see the pattern in it.
So what could be wrong?
I performed the above tests using only one API user. This means that Mongoose only captures the same document again and again. The difference with production is that many different users get into the API, which means that the mongoose receives a lot of different documents.
When I start the nodejs server, the memory grows rapidly to 100 MB-200 MB. It eventually stabilizes around 500 MB. Could this mean that it has a memory leak for each user? As soon as each user visits the API, does it stabilize?
I have included my code below, which describes the general structure of my API. I would really like to know if there is a critical error in my code or any other approach to figuring out what causes high memory.
the code
app.js
var restify = require('restify'); var MongoClient = require('mongodb').MongoClient; // ... setup restify server and mongodb require('./api/message')(server, db);
api / message.js
module.exports = function(server, db) { // Controllers used for retrieving accounts via MongoDB and communication with an external api var accountController = require('../controllers/accounts')(db); var messageController = require('../controllers/messages')(); // Restify bind to put server.put('/api/message', function(req, res, next) { // Token from body var token = req.body.token; // Get account by token accountController.getAccount(token, function(error, account) { // Send a message using external API messageController.sendMessage(token, account.email, function() { res.send(201, {}); return next(); }); }); }); };
Controllers / accounts.js
module.exports = function(db) { // Gets account by a token function getAccount(token, callback) { var ObjectID = require('mongodb').ObjectID; var collection = db.collection('accounts'); collection.findOne({ token: token }, function(error, account) { if (error) { return callback(error); } if (account) { return callback('', account); } return callback('Account not found'); }); } };
Controllers / messages.js
module.exports = function() { function sendMessage(token, email, callback) {
Snapshot heap of alleged leak 