我正在测试具有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项目更易于管理。如果单击并拖动,则可以看到滚动略微不卷曲,但是如果松开鼠标按钮,它将继续滚动得更顺畅。
答案 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中的一个错误并且已经通过其他更新修复(有意或无意)。无论如何,我自己也没有这个问题了。