d3.js realtime streamgraph memory usage This page (full source &amp; demo) displays a 2-channel horizontal d3.js Streamgraph that takes realtime mouse coordinates as data inputs for the graph.

However, it tends to gradually use up an increasing amount of memory until there's none left, both on Chrome and Firefox (on Ubuntu 12.04 x64).  Data is being collected but not released, yet the arrays that hold the incoming mouse coord data are being popped for every push, and I'm missing where the problem is occuring.

I'm working on profiling it, but wondering if any JS experts can eyeball it and see it.  The only dependencies are JQuery and D3.js v3.

&lt;body&gt;
&lt;div id="chart"&gt;&lt;/div&gt;
&lt;script&gt;

    var l = 2; // number of stream channels (layers)
    var n = 100;  // number of samples per layer
    var random = d3.random.normal(0, .2);
    var a = [];
    var b = [];

    /*  Normalize mouse coords to a 0:1 range for d3. */ 
    var denom = { x: $(window).width(), y: $(window).height() };
    var currentMouseCoord = { x: 1, y: 1 };

    /*  While mouse is moving over the streamgraph iframe, replace data stream with realtime normalized mouse coords */
    $(document).mousemove(function(e) {
        currentMouseCoord.x = e.pageX/denom.x;
        currentMouseCoord.y = e.pageY/denom.y;
    }).mouseover();

    /*  When mouse leaves the streamgraph iframe, reset data stream to constant 1 */
    $(document).mouseout(function(e) {
        currentMouseCoord.x = 1;
        currentMouseCoord.y = 1;
    }).mouseout();

    function stream_layers(l, m, o) {
        return d3.range(l).map(function(d,i) {
            if (i == 0) {
                for (idx = 0; idx &lt; m; idx++) a[idx] = currentMouseCoord.x;
                return a.map(stream_index);
            } else if (i ==1) {
                for (idx = 0; idx &lt; m; idx++) b[idx] = currentMouseCoord.y;
                return b.map(stream_index);
            }
        });
    }

    function update_layers(l, m, o) {
        return d3.range(l).map(function(d,i) {
            if (i == 0) {
                a[m] = currentMouseCoord.x;
                return a.map(stream_index);
            } else if (i == 1) {
                b[m] = currentMouseCoord.y;
                return b.map(stream_index);
            }
        });
    }

    function stream_index(d, i) {
        return {x: i, y: Math.max(0, d)};
    }

    var data0 = d3.layout.stack().offset("wiggle")(stream_layers(l,n,0));
    var data1 = d3.layout.stack().offset("wiggle")(stream_layers(l,n,0));

    //var color = d3.interpolateRgb("#aad", "#556");
    var color = d3.interpolateRgb("#f30", "#fdb");

    var w = $(window).width();
    var h = 150;
    var mx = n - 1;
    var my = d3.max(data0.concat(data1), function(d) {
            return d3.max(d, function(d) {
            return d.y0 + d.y;
            });
        });

    var area = d3.svg.area()
        .x(function(d) { return d.x * w / mx; })
        .y0(function(d) { return h - d.y0 * h / my; })
        .y1(function(d) { return h - (d.y + d.y0) * h / my; });

    var vis = d3.select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h);

    vis.selectAll("path")
        .data(data0)
        .enter().append("path")
        .style("fill", function() { return color(Math.random()); })
        .attr("d", area);

    function transition() {

        a.push(.01 + .01*Math.random());
        b.push(.01 + .01*Math.random());
        data0 = d3.layout.stack().offset("wiggle")(update_layers(l,n,0));

        vis.selectAll("path").data(data0).attr("d", area).attr("transform", null).transition().duration(40).ease("linear").attr("transform", "translate(" + -w/n + ")").each("end", function (d,i) { if (i==0) transition();});

        a.shift();
        b.shift();
    }

    $(document).ready(transition());

&lt;/script&gt;
I am happy your problem is solved. All in all, your code looks solid, my review is mostly nitpicking:


I am all for spartan coding, but you have far too many 1 and 2 character variables, you ought to use more meaningful variables.
Try to have 1 var block at the top. More specifically, you declare data0 after declaring the function stream_layers, there is no need for that.
Please use lowerCamelCase coding, so update_layers -> updateLayers
There is no need to call .mouseover(); after setting the listener, especially since you also call .mouseout(); afterwards for which there is also no need as you already set x and y to 1 with var currentMouseCoord = { x: 1, y: 1 };
You can drop curly braces after loops, please don't drop newlines.
vis.selectAll("path").data(data0).attr.... in transition() really should be broken out into multiple lines.