HTML5 Canvas在Chrome上速度较慢,但​​在FireFox上速度很快

时间:2011-11-01 11:11:20

标签: javascript performance firefox google-chrome html5-canvas

我正在测试具有4 GB RAM的双核2.8 GHz Pentium Windows 7系统上的Chrome 15.0.874.106m(以及具有大量内存的高速加速视频卡),我正在测试FireFox 7.0.1具有2 GB RAM的单核1.6 GHz Athalon Windows Vista笔记本电脑。然而,FireFox系统的性能比Chrome系统高出约10倍(根据我的视觉估计,是FPS的10倍)。

我看到的大多数帖子在FireFox和Chrome上表现不佳,但在这里我似乎有一个严重逆转的情况。关于什么可能对此负责的任何想法?我正在测试的HTML文件(单个文件,没有依赖项)大约是33 MB(压缩16 MB),可用here

这是HTML5 canvas performance on small vs. large files的后续行动。

我发现了chrome:// tracing,这有助于我通过chrome profiler运行问题文件来获取这些配置文件结果:

修改: 结果已删除,我收到了一些新的更有趣的结果,我将在新版块中介绍(见下文)。 结束编辑

我还发现了--show-fps-counter,它显示滚动运行大约3.5 FPS。但我还不清楚问题出在哪里。

我还找到了--use-gl开关并尝试了桌面,egl和osmesa。对于osmesa来说,性能似乎最好,但只是勉强。我无法确切知道多少因为show-fps-counter开关显然不能与use-gl = osmesa一起使用。在另一个系统上,osmesa的性能仍然不如FireFox。

编辑续:由于事件处理中的侥幸,我不知何故进入了一种模式,我可以在不按住鼠标按钮的情况下滚动地图。令我震惊和惊讶的是,滚动非常顺利!通过一些额外的编辑(即删除处理mouseup事件的代码),我切换了代码,以便我永远不需要按住按钮进行滚动。瞧,只要我没有按住鼠标按钮,我就可以始终顺利滚动非常。因此,我使用chrome://跟踪使用和不按住鼠标按钮来跟踪行为。我的结果如下。

这是平滑滚动而无需按住鼠标按钮:

Selection summary:
 RenderWidget::OnHandleInputEvent                       :   1340.968ms     212 occurrences
 RenderWidget::InvalidationCallback                     :      7.867ms      27 occurrences
 RenderWidget::OnUpdateRectAck                          :      1.319ms     173 occurrences
 RenderWidget::OnSwapBuffersComplete                    :    129.018ms     173 occurrences
 V8EventListener::callListenerFunction                  :   1306.923ms     173 occurrences
 RenderWidget::DoDeferredUpdate                         :    120.033ms     204 occurrences
 EarlyOut_UpdateReplyPending                            :      0.004ms       4 occurrences
 EarlyOut_SwapStillPending                              :      0.181ms     165 occurrences
 CommandBufferHelper::WaitForToken                      :      8.358ms       3 occurrences
 WebViewImpl::layout                                    :       1.24ms     190 occurrences
 CCLayerTreeHost::updateLayers                          :     34.726ms     173 occurrences
 CCLayerTreeHost::commitTo                              :     24.426ms     173 occurrences
 CCLayerTreeHostImpl::drawLayers                        :     24.483ms     173 occurrences
 LayerRendererChromium::present                         :      8.434ms     173 occurrences
 EarlyOut_NoPendingUpdate                               :      0.018ms      17 occurrences
 CommandBufferProxy::FlushSync                          :      8.307ms       3 occurrences
 CCLayerTreeHost::updateLayers::calcDrawEtc             :     15.871ms     173 occurrences
 LayerRendererChromium::drawLayers                      :     23.441ms     173 occurrences
 RenderWidget::OnSwapBuffersPosted                      :      0.185ms     173 occurrences
 RendererGLContext::SwapBuffers                         :      4.431ms     173 occurrences
 LayerRendererChromium::drawLayersInternal::calcDrawEtc :     10.783ms     173 occurrences
 GpuCommandBufferStub::OnFlush                          :      7.581ms       3 occurrences
 GpuCommandBufferStub::OnAsyncFlush                     :   2825.339ms     352 occurrences
 GpuCommandBufferStub::OnEcho                           :       0.83ms     173 occurrences
 GpuScheduler:PutChanged                                :   2823.239ms     355 occurrences
 GLES2DecoderImpl::HandleTexImage2D                     :      5.779ms       6 occurrences
 GLES2DecoderImpl::HandleTexSubImage2D                  :      1.784ms       3 occurrences
 GLES2DecoderImpl::HandleSwapBuffers                    :   2387.561ms     173 occurrences
 GLContext::SwapBuffers                                 :   2384.623ms     173 occurrences
 ScheduledAction::execute                               :      2.453ms      16 occurrences
 v8.compile                                             :      1.037ms      14 occurrences
 v8.run                                                 :      3.142ms      14 occurrences
 EarlyOut_NotVisible                                    :      0.021ms      14 occurrences
 RenderWidgetHost::ForwardMouseEvent                    :      7.465ms     538 occurrences
 RenderWidgetHost::OnMsgInputEventAck                   :      5.218ms     212 occurrences
 RenderWidgetHost::OnMsgUpdateRect                      :      4.172ms     173 occurrences
 RenderWidgetHost::ForwardInputEvent                    :      4.551ms     212 occurrences
*Totals                                                 :  13535.811ms    5332 occurrences

Selection start                                         :    986.276ms
Selection extent                                        :   3320.488ms

按住鼠标按钮时,这是不稳定/慢速滚动:

Selection summary:
 RenderWidget::OnHandleInputEvent                       :   3852.921ms      61 occurrences
 RenderWidget::InvalidationCallback                     :      4.549ms      61 occurrences
 RenderWidget::OnUpdateRectAck                          :      1.235ms      40 occurrences
 RenderWidget::OnSwapBuffersComplete                    :     20.684ms      40 occurrences
 V8EventListener::callListenerFunction                  :    357.075ms      39 occurrences
 RenderWidget::DoDeferredUpdate                         :     25.208ms     132 occurrences
 EarlyOut_SwapStillPending                              :      0.004ms       6 occurrences
 EarlyOut_UpdateReplyPending                            :      0.032ms      32 occurrences
 CommandBufferHelper::WaitForToken                      :       8.09ms       3 occurrences
 WebViewImpl::layout                                    :      0.346ms      78 occurrences
 CCLayerTreeHost::updateLayers                          :      7.805ms      40 occurrences
 CCLayerTreeHost::commitTo                              :      4.727ms      40 occurrences
 CCLayerTreeHostImpl::drawLayers                        :      9.449ms      40 occurrences
 LayerRendererChromium::present                         :      1.122ms      40 occurrences
 EarlyOut_NoPendingUpdate                               :      0.038ms      38 occurrences
 CommandBufferProxy::FlushSync                          :       8.05ms       3 occurrences
 CCLayerTreeHost::updateLayers::calcDrawEtc             :      3.694ms      40 occurrences
 LayerRendererChromium::drawLayers                      :      9.177ms      40 occurrences
 RenderWidget::OnSwapBuffersPosted                      :      0.035ms      40 occurrences
 RendererGLContext::SwapBuffers                         :      0.684ms      40 occurrences
 LayerTextureUpdaterCanvas::paint                       :      0.483ms       1 occurrences
 LayerTextureSubImage::uploadWithMapTexSubImage         :       0.02ms       1 occurrences
 LayerRendererChromium::drawLayersInternal::calcDrawEtc :      2.329ms      40 occurrences
 GpuCommandBufferStub::OnFlush                          :      7.326ms       3 occurrences
 GpuCommandBufferStub::OnAsyncFlush                     :     226.88ms     121 occurrences
 GpuCommandBufferStub::OnEcho                           :      0.377ms      40 occurrences
 GpuScheduler:PutChanged                                :      230.2ms     124 occurrences
 GLES2DecoderImpl::HandleTexImage2D                     :      5.705ms       8 occurrences
 GLES2DecoderImpl::HandleTexSubImage2D                  :      2.057ms       4 occurrences
 GLES2DecoderImpl::HandleSwapBuffers                    :    113.857ms      40 occurrences
 GLContext::SwapBuffers                                 :    113.377ms      40 occurrences
 ScheduledAction::execute                               :     12.708ms      83 occurrences
 v8.compile                                             :      1.982ms      25 occurrences
 v8.run                                                 :      4.499ms      25 occurrences
 EarlyOut_NotVisible                                    :      0.022ms      25 occurrences
 RenderWidgetHost::ForwardMouseEvent                    :      4.671ms     640 occurrences
 RenderWidgetHost::OnMsgInputEventAck                   :      1.102ms      61 occurrences
 RenderWidgetHost::OnMsgUpdateRect                      :      0.894ms      40 occurrences
 RenderWidgetHost::ForwardInputEvent                    :      1.527ms      61 occurrences
*Totals                                                 :   5044.941ms    2235 occurrences

Selection start                                         :    956.043ms
Selection extent                                        :   6082.888ms

从这个比较中,我认为Chrome的OnHandleInputEvent实现在这里一直在吃东西。发生了什么事?

效果是可见的,即使在更小/更简单的项目上也不那么明显。 Here's一个只有大约700K的例子,比30+ MB项目更易于管理。如果单击并拖动,则可以看到滚动略微不卷曲,但是如果松开鼠标按钮,它将继续滚动得更顺畅。

2 个答案:

答案 0 :(得分:1)

修改:问题不在于此答案中提出的问题。我还编辑了代码以提供更多信息。


  

BlueMonkMN :从这个比较中,我认为Chrome的OnHandleInputEvent实现在这里一直在吃东西。发生了什么事?

     

效果是可见的,即使在更小/更简单的项目上也不那么明显。这是一个只有大约700K的例子,比30+ MB项目更易于管理。如果单击并拖动,则可以看到滚动略微不卷曲,但是如果松开鼠标按钮,它将继续滚动得更顺畅。

查看您的代码(下面),我可以看到您的事件处理程序代码正在调用重绘方法(这就是为什么在事件处理程序中花费了大量的cpu时间)。它应该做的就是更新状态。您的重绘应该在游戏循环中进行,这样可以更加轻松地进行整体管理。

考虑在instanceof中删除MapLayer.prototype.draw的使用,而是找到获取帧的另一种方法。 instanceof是一项代价高昂的操作,并且通常有一种更优雅的方法,不需要这样做。其中一些Tile / Map对象应该通过函数调用而不是数组索引来访问,那么你可以在返回的对象类型上有更多自由,帧可以是更新,整个MapLayer.prototype.draw方法可以更清洁

另外,为什么typeof frames !== 'number'会出现每帧的循环渲染?在调试时,它往往只渲染两帧,但它很突出。

同样,你真的应该在游戏循环中渲染,在事件处理程序中不应该发生任何重大事件。为了更容易,尝试在jsperf.com上为单个帧构建基准,这样您就会知道它在该函数中花费了多少时间。您可以通过对代码的不同方面进行基准测试来缩小瓶颈。

// Section of our code
function beginDrag(e) {
   dragX = e.clientX;
   dragY = e.clientY;
   var srcEl = e.srcElement ? e.srcElement : e.target;
   srcEl.onmousemove = processDrag;
   return false;
}
// **Note** called on mouseout, not mouseup
function endDrag(e) {
   var srcEl = e.srcElement ? e.srcElement : e.target;
   srcEl.onmousemove = null;
}
function processDrag(e) {
   e = e || window.event;
   drag(e.clientX, e.clientY);
   return false;
}
function drag(newX, newY) {
   currentMap.scroll(currentMap.scrollX + newX - dragX, currentMap.scrollY + newY - dragY);
   dragX = newX;
   dragY = newY;
   // --- this should not be executed during an event handler, draw takes place in game loop.
   currentMap.draw(gameViewContext);
}

答案 1 :(得分:0)

我报告的错误(https://code.google.com/p/chromium/issues/detail?id=103148)已被评论为“如果我正确阅读”无法重现,所以我将假设这是Chrome中的一个错误并且已经通过其他更新修复(有意或无意)。无论如何,我自己也没有这个问题了。