-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Fix for memory leak caused by referenced to deferred test functions #2037
Conversation
// in node.js versions 0.11 and 0.12 it seems that large array allocation is very inefficient | ||
// thus causing the respective Travis-CI jobs to run much longer and causing this test | ||
// to sometimes fail due to timeout. | ||
this.timeout(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.timeout
won't actually timeout the test after 1 second, since MemoryLeak's for loop is a blocking operation, and mocha just uses setTimeout
:
Lines 211 to 217 in d811eb9
this.timer = setTimeout(function() { | |
if (!self._enableTimeouts) { | |
return; | |
} | |
self.callback(new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.')); | |
self.timedOut = true; | |
}, ms); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example might help clarify:
$ cat example.js
setTimeout(function() {
console.log(new Date(), 'Timeout!');
}, 1000);
console.log(new Date());
var array = [];
for (var i = 0; i < 20000000; i++) {
array.push({val: i});
}
// $ time node example.js
// Sun Jan 03 2016 13:31:21 GMT-0500 (EST)
// Sun Jan 03 2016 13:31:27 GMT-0500 (EST) 'Timeout!'
//
// real 0m6.837s
// user 0m6.444s
// sys 0m0.425s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification.
The weaker condition of waiting at least 1000ms is good enough in this use case.
The timeout is there because on node.js versions 0.11 and 0.12 on Travis-CI
sometimes take slightly longer than 200ms. (the default timeout) and thus the change
failed there.
see
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my mistake! Makes sense :)
Thanks for the PR! Going over it now! Could you move |
* Cleans up the references to all the deferred functions (before/after/beforeEach/afterEach) | ||
* of a Suite. These must be deleted otherwise it may create a memory leak as those functions may | ||
* reference variables from closures, thus those variables can never be garbage collected as long | ||
* as the deferred functions exist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file appears to mostly follow a 80 char ruler - could you update this doc comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
Actually, rather than an integration test (since it takes 40s+ to run on my laptop) could you add a unit test that verified runnable fns were deleted from a suite? It could be added to it('deletes runnable fn when no longer needed', function(done) {
var test = new Test('test', function() {});
suite.addTest(test);
suite.before(function() {});
suite.beforeEach(function() {});
suite.afterEach(function() {});
suite.after(function() {});
var runner = new Runner(suite);
runner.runTests(function(err) {
// perform assertions here
done();
});
}); |
From which century is that laptop? :) anyhow I see your point as the Travis CI containers are also The problem is that verification of simple property deletion is a much weaker check as it will not detect I think I can do something simple that scans the object graph starting from the Suite and detects
That check will be more dynamic (no fixed property names) and better detect regressions in the future. |
haha that's fair, the 40s is with node v0.12. With Node v4, I'm seeing 8s.
A regression that introduced a smaller memory leak might still go undetected. But your integration test does a good job of catching most cases - e.g. beforeEach fn's magically not being deleted. Others, I'm less worried about. Some reporters (markdown, doc, html) perform simple operations on You make a good point, and I'm happy with the existing integration test if it could be moved under fixtures, as mentioned here: #2037 (comment) A single spec could then be added to |
Hi @danielstjules. I've replaced the test that reproduced the memory leak, but was slow and created a lot of noise in the test report. The new one is:
I've kept it in integration tests as:
What do you think? |
Looking at your latest commit, imagine the following diff: diff --git a/lib/runnable.js b/lib/runnable.js
index 5e1ab76..70ec96d 100644
--- a/lib/runnable.js
+++ b/lib/runnable.js
@@ -42,9 +42,11 @@ module.exports = Runnable;
* @param {string} title
* @param {Function} fn
*/
+var fns = [];
function Runnable(title, fn) {
this.title = title;
this.fn = fn;
+ fns.push(fn);
this.async = fn && fn.length;
this.sync = !this.async;
this._timeout = 2000; Running Would you mind reverting and using the previous integration test, along with my suggestion of placing it in fixtures? A single spec in
|
@bd82 this is awesome! thanks a lot for making a PR for this. really excited for this! hopefully it gets pulled in soon :D |
@danielstjules: I'll revert to the original test and put it in a fixture. np @gumatias, it was an interesting bug giving a chance to learn some memory leak debugging in javascript. :) |
@bd82 Thanks again! Appreciate all your work on this PR :) |
(it/before[Each]/after[Each]). related to #1991.
@danielstjules pleasure to help. :) I've updated the PR to use a fixture with clear description/error messages. |
Looks good! Reporters that use test.fn still work, so that's perfect. :) Thanks again! |
Fix for memory leak caused by referenced to deferred test functions
Related issue here: #2066 |
(it/before[Each]/after[Each]).
related to #1991