重复应用 d3 转换导致的内存泄漏
Memory leak from repeatedly applying d3 transition
我有一个SVG地图和一个间隔,用于轮询数据更改并相应地更新地图上的颜色。 除非我使用过渡淡入新颜色,否则这一切都可以正常工作。 然后选项卡慢慢占用越来越多的内存,直到崩溃。
我做了一个简化的例子,显示了相同的行为:
var size = 500;
var num = 25;
var boxSize = size / num;
function color(d) {
return '#' + Math.random().toString(16).slice(2,8);
}
var svg = d3.select('body')
.append("svg")
.attr("width", size)
.attr("height", size);
var squares = svg.selectAll(".square")
.data(d3.range(num * num))
.enter().append("rect")
.attr("class", "square")
.attr("width", boxSize)
.attr("height", boxSize)
.attr("x", function (d) { return boxSize * (d % num);})
.attr("y", function (d) { return boxSize * Math.floor(d / num); })
.style("fill", color);
function shuffleColors() {
squares.interrupt().transition().duration(500).style("fill", color);
timer = setTimeout(shuffleColors, 1000);
}
var timer = setTimeout(shuffleColors, 1000);
https://plnkr.co/edit/p71QmO
我已经在Linux上的Chromium(49(和Firefox(45(中尝试过。 前者似乎爆炸得更快,但两者都有问题。 在内存分析器中,它都不会显示,但 about:memory 显示选项卡在增长。
我从文档中的理解是,向选择添加过渡会用相同的名称替换任何以前的过渡(包括空名称(,但我的假设是为实现过渡而创建的函数实际上并没有被抛弃。 但是我还没有设法让他们确认这一点或解决这个问题。
所以,一个由两部分组成的问题:
- 这是 d3 转换的正确使用,还是有更正确的方法来完成我想要的?
- 如果我正确使用转换,如何让它停止泄漏内存?
编辑:
- 根据 Blindman67 的评论,我将其更改为使用 setTimeout 并稍微小一点。我试图模拟的原版更小更慢,但需要几个小时才能最终变大,所以我试图加快速度。 这个版本似乎仍在增长,至少对我来说是Chromium上的。
- 我观察到
d3_selectionPrototype.transition
每次都会使用递增的ID制作一个新d3_transition
,但如果旧的ID被垃圾收集,那很好。我仍然无法指出它是否或为什么被保留。
我相当确定它必须在这里做这篇文章:
function shuffleColors() {
squares.interrupt().transition().duration(500).style("fill", color);
timer = setTimeout(shuffleColors, 1000);
}
var timer = setTimeout(shuffleColors, 1000);
每次调用函数shuffleColors()
时,它都会再次调用自身,实质上是一个没有基本情况的递归循环。它没有立即爆炸的原因是每次调用函数都会延迟 1000 毫秒,但是,我认为完成squares.interrupt().transition().duration(500).style("fill", color);
所需的时间比调用setTimeout()
的时间要长。因此,即使您每 1000 毫秒调用一次它,它也可能会以某种方式堆叠,因为某些颜色变化可能需要更多时间来处理。
虽然它在技术上不应该这样做,但知道JavaScript的异步性,它可能有一个角色。我建议这样做并报告结果:
function shuffleColors() {
squares.interrupt().transition().duration(500).style("fill", color);
}
var timer = setInterval(shuffleColors, 1000);
如果需要,您也可以随时致电clearInterval(timer)
。 创建setInterval()
正是出于您实现setTimeout()
的原因。
编辑:这可能无法完全工作,因为您可能仍然需要等待颜色更改完成,但是,这至少是一种更清洁的方法。您可以实现某种wait()
函数来等待颜色更改完成。
虽然矢量 (SVG( 图像是轻量级的,但与解码 JPEG 图像相比,不断更改颜色或类似内容所需的处理量是巨大的。
如果使原始图像大小小得多,然后将其扩展到分辨率,则可能会找到更好的结果。您可以制作一个 100x100 的画布 SVG 并将其扩展到 2000x2000 或其他尺寸,这样它就不必绘制这么大的图像。
- 重复应用 d3 转换导致的内存泄漏
- IE7中的blockUI插件内存泄漏25kb
- Javascript闭包-如何防止内存泄漏
- jQuery Draggable:内存泄漏
- "检测到可能的EventEmitter内存泄漏”;使用Gulp+Watchify+Factor捆绑包
- 在Dojo类中递归调用setTimeout时是否存在内存泄漏
- 是内存泄漏
- 将处理程序留在img.onload上是内存泄漏
- 具有并发sse连接的node.js内存泄漏
- 简单对象的Javascript内存泄漏
- WeakMap是否会将我从父/子关系的内存泄漏中拯救出来
- Javascript绘制画布内存泄漏
- Node.js”;检测到EventEmitter内存泄漏”;
- 正在清理内存泄漏
- 递归Javascript对象是否会导致任何问题(内存泄漏)
- Angular JS$编译服务导致$watch内存泄漏
- 如何防止和防范闭包内存泄漏
- 跟踪 JavaScript 内存泄漏的工具
- 页面刷新后javascript内存泄漏有问题吗?为什么?
- XMLHttpRequest循环内存泄漏