Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Memory leak when calling Plotly.plot() in Loop with small example code

Hello everybody,

I am using plotly.js in a bigger Asp.Net Webforms application (telerik controls are used as well) and stumbled upon memory leaks (tested in IE11). I tried different things out and created a small example (See code bellow). In the code I create a histogram plot with 4000x4000 random data points and plot them 10 times in the loop (Press the “Replot Traces” Button). I would expect that the new plot()-call in the next iteration just “overrides” the plot of the iteration before. But the memory usage increases until I run out of memory…

Deleting the whole plot or calling the GC does not help (the memory decreases just a little bit).

<head>
  <!-- Plotly.js -->
  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
  <div id="myDiv"><!-- Plotly chart will be drawn inside this DIV --></div>
  <div id="delete" style="margin-left:80px;">
      <button style="background: red;" onclick="deletePlot()">Delete/Purge</button>
  </div>

  <div style="margin-left:80px;">
      <button style="background: green;" onclick="plotAll()">Replot Traces</button>
  </div>

  <div style="margin-left:80px;">
      <button style="background: blue;" onclick="CallGC()">Call GC</button>
  </div>

    <script>
        function deletePlot(){
            Plotly.purge('myDiv');
        }

        function plotAll()
        {
            var n = 4000

            var s2dArray = '[';
            for (var i=0; i <n; i++)
            {
                s2dArray = s2dArray.concat('[');
                for (var j=0; j <n; j++)
                {
                    s2dArray = s2dArray.concat(Math.round((Math.random() * 100) + 1));
                    if(j < n-1)
                    {
                        s2dArray = s2dArray.concat(',');
                    }
                }
                s2dArray = s2dArray.concat(']');
                if(i < n-1)
                {
                    s2dArray = s2dArray.concat(',');
                }
            }
            s2dArray = s2dArray.concat(']');

            var data = [
            {
                z: JSON.parse(s2dArray),
                type: 'heatmap'
                }
            ];

            for(var i =0; i<10; i++)
            {
                Plotly.plot('myDiv', data, {}, {showSendToCloud: true});
                console.log(i);
            }
        }

        function CallGC()
        {
            CollectGarbage();
        }
    </script>
</body>

Did anybody have similar problems and has an idea how to handle this. Is there a way to completely reset/clear plotly without reloading the whole page (because in my big application I am using Ajax and cannot reload the whole page everytime)?.

Thanks in advance!

Noting that each Plotly.plot adds a new trace to the scene (i.e. over previous heatmap),
wondering if you tried using Plotly.newPlot (or Plotly.react) instead of Plotly.plot there?

Hi archmoj, thank you for your help. The Plotly.newPlot() call did help, but created an memory overflow anyways (in my sample code in 19 iterations). I will try to look into it closer, but its quite confusing…

Or maybe let me ask another question: What do I need to do, to avoid memory overflows, if I load the plots in a small part of the Page via AJAX (Telerik-Controls). By updating, the whole html code in that part of the page is replaced (i am not updating existing plots, i am am completely replacing it). Are there global variables in the plotly library that need to be deleted?

Could you please share a codepen demonstrating the problem?
Thanks!

Hi, sure! https://codepen.io/Yeritsyano/pen/GRRBQOz
Just click on the green button to trigger the plotting. It will call newPlot() 100 times and at some point I get a memory overflow.

The 4000x4000 grid is quite large. Have you tried using Plotly.react instead of Plotly.newPlot?

For this particular problem react was better. I am tried to check if it solves the other problems I had. Are there any reasons not to use .react()?

Good. That is the better way.