【问题标题】:Optimizing JavaScript for multiple browser display at high fps优化 JavaScript 以实现高 fps 的多浏览器显示
【发布时间】:2017-11-21 21:40:04
【问题描述】:

我有一个使用画布绘制高速显示的 FFT。我想优化代码以使 16 个浏览器窗口以 60 fps 或接近它的速度同时显示。现在在我的机器上,它以 5 fps 的速度运行,同时显示 16 个窗口。

我想知道是否有更好的方法来优化我的代码以提高绘图性能。

有了这个,我可以在最多四个同时浏览器窗口中获得 60 fps,但之后 fps 会显着下降。现在,我正在将所有文件加载到数组缓冲区中,并在 drawFFT() 中操作点并同时绘制它们。在同时运行的多个浏览器窗口上提高 fps 性能的任何提示?

【问题讨论】:

  • 为什么是 16 个浏览器?每个都使用资源和 CPU 周期。使用 4 个窗口(每个 CPU 内核一个)每个显示 4 个,或者一个显示全部会更有效。几乎没有改进的空间,代码可能只有几个 %(你需要 1200% 的改进),只有这么多内核,一旦你超过了(猜测你的系统上有 4 个内核),额外的线程将开始互相减慢.每个线程还需要共享一个 GPU,这增加了 CPU 和 GPU 的负担。理想情况下,一个线程来处理 GPU / CPU,然后一些工作人员来管理任何额外的数据需求。
  • 我试图捕捉数字并意识到 Javascript 部分实际上完成得非常快。但是 GPU 需要更长的时间来渲染。我打开的窗口越多,等待 GPU 的时间越长,中间的空闲间隙就越小。它会阻塞并延迟下一个requestAnimationFrame

标签: javascript performance canvas optimization


【解决方案1】:

多个窗口上的 60 fps 动画

99.99% 的时间,requestAnimationFrame 制作视觉动画的方式。这是一个很棒的工具,与屏幕刷新率同步,具有很高的计时精度,并且电池友好

这最后一个优势是你的问题:为了省电,浏览器只允许以 60fps 的速度对当前聚焦的窗口进行屏幕同步。所有其他窗口都会延迟,帧速率较低。
由于您希望拥有多个窗口,因此您只能获得一个焦点,因此只有一个以 60 fps 刷新,所有其他窗口将减慢到 5 fps 左右。

如何规避?

WebAudioAPI 确实有自己的低级和高精度时钟系统。
通过“低级”,我的意思是这个时钟系统不绑定到主 js-thread*。在某些实现(chrome)上,所有 WebAudioAPI 甚至都在并行线程上运行。对我们来说更重要的是,这个时钟系统不仅与聚焦窗口相关。这确实意味着我们可以在后台窗口中以 60fps 的速度运行代码。

这是一个基于 WebAudioAPI 时钟的定时循环的简单实现。

(*请注意,虽然时钟不绑定到主 js 线程,但事件处理程序是)。

/*
    An alternative timing loop, based on AudioContext's clock

    @arg callback : a callback function 
        with the audioContext's currentTime passed as unique argument
    @arg frequency : float in ms;
    @returns : a stop function
    
*/
function audioTimerLoop(callback, frequency) {

  var freq = frequency / 1000;      // AudioContext time parameters are in seconds
  var aCtx = new AudioContext();
  // Chrome needs our oscillator node to be attached to the destination
  // So we create a silent Gain Node
  var silence = aCtx.createGain();
  silence.gain.value = 0;
  silence.connect(aCtx.destination);

  onOSCend();

  var stopped = false;       // A flag to know when we'll stop the loop
  function onOSCend() {
    var osc = aCtx.createOscillator();
    osc.onended = onOSCend; // so we can loop
    osc.connect(silence);
    osc.start(0); // start it now
    osc.stop(aCtx.currentTime + freq); // stop it next frame
    callback(aCtx.currentTime); // one frame is done
    if (stopped) {  // user broke the loop
      osc.onended = function() {
        aCtx.close(); // clear the audioContext
        return;
      };
    }
  };
  // return a function to stop our loop
  return function() {
    stopped = true;
  };
}

然后这样称呼它:

var stop_anim = audioTimerLoop(yourCallback, 60); // runs 'yourCallback' every 60ms

然后停止它:

stop_anim();

好的,现在我们可以在模糊的窗口上运行流畅的动画了。

但我想在 16 个窗口上运行它!

不幸的是,浏览器在创建 AudioContext 时会受到硬件限制。 (例如,在我的计算机上,我不能同时运行超过 6 个上下文。)

这里的解决方案是在一个主窗口上运行所有代码

从此主窗口,您将首先

  • 打开所有其他窗口,以便您可以访问它们的内容,
  • 获取画布元素的上下文,
  • 利用这些背景

这样,您在主窗口上有一个更新线程,而所有其他窗口只需要渲染。


Live Example

(请确保允许弹出窗口并禁用您的广告拦截器)。

【讨论】:

    猜你喜欢
    • 2019-04-23
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-21
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多