@jvilk opened this Issue on September 14th 2017 Contributor

This is a somewhat complex memory leak made even more complex by my only vague familiarity with AngularJS. I will do my best to explain what is going on!

Steps to Reproduce

  • Visit the Dashboard of a Piwik installation.
  • Open up the devtools console, and inspect the length of the following property:
    • window.$widgetContent[0].jQuery[long number].$scope.$$listeners.$destroy
    • Note: jQuery randomly generates the long number.
    • Note 2: You have two instances of jQuery on the page, which both use different numbers in their properties. Typically, the larger of the two has the $scope property.
  • Click on the "Dashboard" link in the menu to refresh the dashboard.
  • Re-inspect the property, noting how it has doubled in length.

Cause

compileAngularComponents is to blame; specifically, this line:

https://github.com/piwik/piwik/blob/9c7d7ff1c842132bc8f3f0ff8c296eb7d3959c30/plugins/Morpheus/javascripts/piwikHelper.js#L123

The call to $compile causes AngularJS to register the $destroy handler on the element's scope. However, the scope is never destroyed -- it is re-used across dashboard visits.

Solution

Is it possible to destroy and re-create the scope when you redraw the dashboard? If not, then perhaps you can remove all of these listeners as a hackfix when the dashboard is redrawn?

Alternatively, are you supposed to re-compile these widgets when you revisit the dashboard? I honestly don't know. :-)

Impact

To measure the impact of this leak on Piwik's heap size, I hackfixed the leak by simply removing the line in Angular JS that adds the listener. Here is the result:

piwik_angular_leak

Powered by GitHub Issue Mirror