【问题标题】:Javascript Loop Optimization for Large Data大数据的 Javascript 循环优化
【发布时间】:2016-06-17 06:51:23
【问题描述】:

我正在处理一个小项目,它处理一个非常大的数组(1024 个项目),将数组中的数据输出到文档上的 1024 个单独元素(是的,我尝试了画布,但它们太模糊了对于我正在做的事情)。

我需要的是尽可能优化这个循环的方法。

for(var i = 0; i < 1024; i++){
    elems[i].style.height = data[i] + 'px';
    elems[i].style.backgroundColor = 'rgb(0,' + data[i] + ',' + (255 - data[i]) + ')';
}

对于数组data 中的每个项目,它总是1024 个项目,循环设置存储在elems 中的页面上的1024 个div 之一的高度,并将其颜色设置为值越大越绿,值越低越蓝。 data 中的值始终介于 0 到 255 之间。循环在每个 animationFrame 运行,我不能让它随着时间的推移分段进行。数据必须实时更新。

我的主要问题是运行循环会输出非常低的 FPS 计数,通常约为 15fps。我的问题是:

我可以通过哪些方式优化上面的循环以尽可能快地运行?每个渲染帧都会实时更新数据。我将高 FPS 作为我的主要目标。这可能吗?

如果有帮助,我正在使用新的 Google Chrome 音频分析器制作音乐可视化工具。

我也可以在将来需要处理或显示非常大的数据集时看到这方面的帮助。每种方法,即使在很大程度上不可读(这就是 /*comments*/ 的用途),都有帮助!

【问题讨论】:

  • 1024 一点都不大...
  • 1024 项不是很大。画布以什么方式“模糊”?
  • 为什么需要Math.round?它不总是一个整数吗?另外,您能否创建一些我们可以自己测试的示例?
  • 画布总是模糊的,因为它们使用不同的像素比率 - 基于非常成功的网络搜索,我发现我需要来自浏览器的值以某种方式更改比率 - 我的浏览器没有报告的值准确,因此没有工作。我在制作项目时将 Math.round() 放在那里 - 在我意识到它是整数被减去之前,我对 JS 奇怪的浮点问题感到偏执。我忘了删除它。 1024 件物品对我来说似乎很大,因为我正在做的事情很激烈。 DOM 很慢 - 每个值两次 DOM 交互是每个动画帧 2048 次 DOM 交互。
  • 查看这个关于延迟 dom 渲染的 SO。 stackoverflow.com/questions/1392068/… 您的问题可能源于 Chrome 如何在循环的每次迭代中重排 DOM。如果您先隐藏该元素或在父项的克隆上进行更改,然后立即全部更新,您可能会看到一些性能改进。

标签: javascript loops optimization


【解决方案1】:

我知道这本身并不能很好地回答,但我想在这里展示动画非常快,并且不能在评论中这样做。

除了您显示的代码之外,您的代码中可能还有其他内容。我制作了这个小演示来尝试了解可能发生的情况,并且我通常会获得大约 50fps(在 Win 8.1 上的 Chrome 51 中)。它确实取决于您的 DOM 结构以及您同时在页面上进行的其他操作...

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

var start;

function updatePositions(timestamp) {
  var container = document.getElementById('container');
  var elems = container.children;
  for (var i = 0; i < 1024; i++) {
    var itemValue = getRandomInt(0, 255);
    elems[i].style.height = itemValue + 'px';
    elems[i].style.backgroundColor = 'rgb(0,' + itemValue + ',' + (255 - itemValue) + ')';
  }
  start = start || timestamp;
  var duration = timestamp - start;
  if (duration < 5000) {
    window.requestAnimationFrame(updatePositions);
  }
}

function initialize() {
  var items = [];
  for (var i = 0, z = 1024; i < z; i++) {
    items.push('<div id="item' + i + '">' + i + '</div>');
  }
  container.innerHTML = items.join('');
  window.requestAnimationFrame(updatePositions);
}

window.onload = initialize;
<div id="container">
</div>

【讨论】:

  • 我的代码实际上是从源中提取信息。它让audioContext 向audioAnalyzer 播放音频。您似乎使用了随机数。对于页面上的所有其他内容,我在可视化工具旁边只有一行控件,仅使用文本以及一些输入字段和按钮。例如,nrabinowitz 的平均速度为 40fps,而 Mike 在我的机器上的平均速度约为 35fps。 (惠普笔记本电脑,win10上的铬)。如果允许我共享指向站点本身的链接,我只是启动了 Web 服务器。 (只允许一次运行几个小时,无需付费订阅)
  • 我在学校运行过的其他设备是 Chromebase 和 Chromebook,结果相似
  • 是的@MineAndCraft12,我用的是随机的,因为我没有玩过音频,我不确定你是否可以从沙盒 iframe 访问音频(这是 sn-ps 运行的内容) .只是想从您拥有的代码中表明,它不应该很慢。可能是 audioAnalyzer 中的某些东西减慢了速度,而不是动画本身。
  • 不是在抨击它,只是注意到它对性能的影响。我在我的分析器中看到 71% 的 JS 花费的时间是所谓的(程序),而 15% 是可视化器从分析器中获取数据。另外 14% 是 for 循环,剩下的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多