HTML5 canvas slows down in Chrome but runs fast on FireFox

I am testing Chrome 15.0.874.106m on a dual-core 2.8 GHz Pentium Windows 7 system with 4 GB of RAM (and a highly accelerated graphics card with a large amount of memory), and I am testing FireFox 7.0.1 on a single-core 1.6 GHz Athalon Windows Vista Notebook with 2 GB of RAM. Nevertheless, the FireFox system surpasses the Chrome system by about 10 times (10 times compared to FPS in my visual assessment).

Most of the messages I see experience slower performance in FireFox and Chrome, but here I seem to have made a big difference. Any ideas on what could be causing this? The HTML file (single file, no dependencies) that I'm testing is about 33 MB (compressed 16 MB) and is available here .

This is a continuation of HTML5 canvas performance on small and large files .

I discovered chrome: // trace, which helped me get these profile results from running the problem file through the chrome profiler:

Edit: The results are deleted, I received several new much more interesting results, which I will describe in a new section (see below). Edit end

I also found -show-fps-counter, which showed that scrolling works around 3.5 FPS. But I still do not understand where the problem is.

I also found the -use-gl switch and tried the desktop, egl and osmesa. The performance seemed the best with osmes, but only with difficulty. I could not say for sure how much due to the fact that the show-fps-counter switch does not seem to work in conjunction with use-gl = osmesa. osmesa still doesn't work much like FireFox on another system.

Edit Continue: Due to an accident in event processing, I somehow got into the mode where I could scroll the map without holding the mouse button. To my shock and amazement, it rolled very smoothly! With a few additional changes (namely deleting the code that processes the mouseup event), I switched the code so that I never need to hold down the button to scroll. Listen, I can scroll very smoothly sequentially until I hold the mouse button. Thus, I profiled / tracked the behavior using chrome: // tracking with and without holding down the mouse button. My results are below.

This is a smooth scroll without holding down the mouse button:

  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

And this is an intermittent / slow scroll while holding down the mouse button:

 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 occurrendersVentListFender8VerderFencermsVentRenderVent 35.0 RenderWercesVentrencesVent 35FenrendermsVentrencesVentRendersVentSwenterrencesVent 351 eventRenders : 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 CCLayerTersCeremitres CCleayer : 4.727ms 40 occurrences CCLayerTreeHostImpl :: drawLayers: 9.449ms 40 occurrences LayerRendererChromium :: present: 1.122ms 40 events LayerRendererChromium :: dr  awLayers: 9.177ms 40 occurrences RenderWidget :: OnSwapBuffersPosted: 0.035ms 40 occurrences RendererGLContext :: SwapBuffers: 0.684ms 40 occurrences LayerTextureUpdaterCanvas :: paint: 0.483ms 1 occurrences LayerTextureSubImage :: uploadWithMenreremsermserms 2.332ms : 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.un EarlyOut_NotVisible: 0.022ms 25 occurrences RenderWidgetHost :: ForwardM  ouseEvent: 4.671ms 640 occurrences RenderWidgetHost :: OnMsgInputEventAck: 1.102ms 61 occurrences RenderWidgetHost :: OnMsgUpdateRect: 0.894ms 40 occurrences RenderWidgetHost :: ForwardInputEvent: 1.527ms 61 occurrences * Totals: 5044.982ms Selection 6035.843ms Selection 

From this comparison, it seems to me that the implementation of Chrome OnHandleInputEvent is constantly growing. What's happening?

The effect is visible, just not so pronounced even in much smaller / simpler projects. Below is an example that only contains about 700K, which is a more manageable thing to test than a project with more than 30 megabytes. If you click and drag, you can see the scrolls slightly intermittently, but if you release the mouse button, it will continue to scroll much more smoothly.

+4
source share
2 answers

The reported error ( https://code.google.com/p/chromium/issues/detail?id=103148 ) has since been marked as "unable to reproduce," if I read it correctly, m will work on the assumption that it was a bug in Chrome and fixed (intentionally or not) by other updates. In any case, I no longer have a problem.

0
source

Change The problem is not related to the issues raised in this answer. I also edited the code to be a little more informative.


BlueMonkMN . From this comparison, it seems to me that the implementation of Chrome OnHandleInputEvent is constantly growing. What's happening?

The effect is visible, just not so pronounced even in much smaller / simpler projects. Here is an example of just about 700K, which is a more manageable thing to test than a 30+ MB project. If you click and drag, you can see the scrolls slightly intermittently, but if you release the mouse button, it will continue to scroll much more smoothly.

Looking at my code (see below), I see that your event handler code calls the redraw methods ( therefore, most of the processor time is spent on event handlers ). All he has to do is update the state. Your redrawing should take place in your Game loop , which will simplify management in general.

Try removing the use of instanceof in MapLayer.prototype.draw and instead find another way to get frames. instanceof is an expensive operation, and often there is a much more elegant approach that does not require this. Some of these Tile / Map objects should be accessible through function calls, not array indexes, then you can have more freedom with regard to the type of the returned object, frames can be updates, and the whole MapLayer.prototype.draw method can be much cleaner.

Also, why is there a loop representing each frame if typeof frames !== 'number' ? When debugging, it tends to produce only two frames, but it stands out.

Again, you really have to be rendering in the game loop, nothing should happen in event handlers. To simplify the task, try building a benchmark for one frame on jsperf.com , so you know how much time is spent on this function. And you can narrow the bottleneck by comparing different aspects of your code.

 // 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
source

Source: https://habr.com/ru/post/1379120/


All Articles