我正在具有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差。

编辑续:由于事件处理中的意外,我以某种方式进入了一种模式,无需按住鼠标键即可滚动 map 。令我震惊和惊讶的是,它的滚动非常平稳!通过进行一些其他编辑(即,删除处理mouseup事件的代码),我切换了代码,因此不再需要按住按钮来滚动。瞧,只要不按住鼠标按钮,我就可以持续非常流畅地滚动。因此,我在使用chrome:// tracing的情况下(没有按住鼠标按钮的情况下)来分析/跟踪了行为。我的结果如下。

无需按住鼠标键即可平滑滚动:

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

选择开始:986.276ms
选择范围:3320.488ms

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

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

选择开始:956.043ms
选择范围:6082.888ms

通过这种比较,在我看来,Chrome的OnHandleInputEvent实现在这里一直在吃光。这是怎么回事?

这种效果是可见的,即使在更小/更简单的项目中也没有那么明显。 Here's一个只有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);
}

关于javascript - HTML5 Canvas在Chrome上速度较慢,但​​在FireFox上速度较快,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7965592/

10-13 08:53