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 fixes #724

Merged
merged 4 commits into from Jul 8, 2016
Merged

Memory leak fixes #724

merged 4 commits into from Jul 8, 2016

Conversation

monfera
Copy link
Contributor

@monfera monfera commented Jul 6, 2016

Commit c123ebc helps a lot - not only with a significantly reduced (though not yet fully eliminated) memory leak, but also, causes a stop for the point picker requestAnimationFrame loop, so the purportedly idempotent plotNew function doesn't leave behind an orphaned, CPU eating rAF loop with potentially large arrays.

It may be that part of the residual leakage is related to the rAF acting as a closure with variable capture: even if the rAF is stopped by causing stop = true via the intended destroy sequence, maybe some state is still retained. Check this among other things.

Unrelated to the leakage, we identified the rAF based approach as something we might want to improve upon.

PR is WIP not only because it's not a full fix and it's as yet untested, but also the code will probably need to be more generic (e.g. now it shoots for _scene2d but the 3D case may be analogous).

…AF never stops; 2) scene2d.destroy should destroy the traces

(cherry picked from commit 8f6f2dd)
@@ -809,6 +809,16 @@ plots.purge = function(gd) {
// remove modebar
if(fullLayout._modeBar) fullLayout._modeBar.destroy();

if(fullLayout._plots) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Gl context deletion should be already taken care of via Plots.cleanPlot which is currently called in Plots.supplyDefaults here and more explicity in Plotly.purge here.

Maybe something is up with the gl2d clean method?

Copy link
Contributor Author

@monfera monfera Jul 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@etpinard I was chasing a point pick regression but back on this now. The root call is a Plotly.newPlot. It does call supplyDefaults and cleanPlot. But basePlotModules is [] empty so it doesn't even reach the point of testing if there is a _module.clean metod. I'm carrying on looking, based on your hint, but wanted to mention it in case it rings a bell.

P.S. In fact, oldFullLayout looks like an empty object. I'm swimming upstream.

Copy link
Contributor Author

@monfera monfera Jul 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... looks like plots.purge deletes gd._fullLayout just before Plotly.plot is called (the latter of which then calls supplyDefaults which calls cleanPlot) so by the time cleanPlot is called, there's no longer information about what to clean.

I'm in a bit of a conundrum as there's a big amount of statefulness and I'm concerned that a purported fix from me (e.g. not delete gd._fullLayout in purge so the info stays around) has unintended, undesirable consequences, besides the fact that it would allow proper working of the _module.clean loop. So I'd rather get input @etpinard before shoehorning in something that looks like a fix.

Plotly.newPlot = function(gd, data, layout, config) {
    gd = getGraphDiv(gd);
    Plots.purge(gd);   // <= this deletes gd._fullLayout
    return Plotly.plot(gd, data, layout, config);  // <= cleanPlot would rely on gd._fullLayout
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so by the time cleanPlot is called, there's no longer information about what to clean.

Wow. That's bad. Nice catch.

I think the best solution at the moment would be to add

 // remove gl contexts
Plots.cleanPlot([], {}, fullData, fullLayout);

to Plotly.newPlot before it calls Plots.purge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @etpinard! This

Plotly.newPlot = function(gd, data, layout, config) {
    gd = getGraphDiv(gd);

    // remove gl contexts
    Plots.cleanPlot([], {}, gd._fullData || {}, gd._fullLayout || {});

    Plots.purge(gd);
    return Plotly.plot(gd, data, layout, config);
};

seems to go ahead and ultimately call scene2d destroy method which has my few lines of trace line disposals. I'll double-check via remeasuring the memory footprint, but for that test I have to cherrypick it into the local branch which also has the undo history limit.

@etpinard
Copy link
Contributor

etpinard commented Jul 7, 2016

@monfera thanks for looking into this!

@monfera monfera changed the title [WIP] Memory leak fixes Memory leak fixes Jul 8, 2016
@monfera
Copy link
Contributor Author

monfera commented Jul 8, 2016

@etpinard I pushed the change you suggested, and the pick fix (just brought forward the trace dispose loop), so I think it's ready for review.

@@ -835,6 +835,10 @@ Plotly.redraw = function(gd) {
*/
Plotly.newPlot = function(gd, data, layout, config) {
gd = getGraphDiv(gd);

// remove gl contexts
Plots.cleanPlot([], {}, gd._fullData || {}, gd._fullLayout || {});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

@monfera would you adding a test case for checking that Plotly.newPlot does clear existing gl contexts similar to the one for Plots.cleanPlot ?

Thanks in advance.

@etpinard
Copy link
Contributor

etpinard commented Jul 8, 2016

@monfera Looks good!

Thanks again for catching that newPlot bug.

@etpinard
Copy link
Contributor

etpinard commented Jul 8, 2016

Great tests! Thanks @monfera !!

@etpinard etpinard merged commit e8b7e0c into plotly:master Jul 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants