Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance: No rendering if invisible & lazy sync #19

Closed
klokan opened this issue Aug 8, 2014 · 19 comments
Closed

Performance: No rendering if invisible & lazy sync #19

klokan opened this issue Aug 8, 2014 · 19 comments
Labels
Milestone

Comments

@klokan
Copy link
Member

klokan commented Aug 8, 2014

In this moment ol.View and Cesium camera are constantly synchronized (as if both are visible) and both libraries render the map with all layers, features, etc. This happens also in the moment where one of 2D or 3D is not visible on screen or when in a "stacked mode" (3D overlaying 2D in the same DOM container element).

Performance may be improved if we disable rendering or stop synchronization of the carmera/view between the two projects whenever possible. But this may bring some implications on how the wrapper may or may not be used by programmers.

A simple solution not breaking anything may be just stop unwanted rendering, but keep view+camera constantly synchronized.

It means:

  • do not call this.scene_.render(); if Cesium is not enabled
  • stop rendering on ol3 side (how? via setting a copy of existing ol.view and keeping synchronized the original ol.view object which may be set back to ol3 when sync should be restored?)

An advanced implementation could be even more clever. We could detect stacked mode and delay or completly stop synchronization on view, and enforce it only if required from the wrapper code via a helper function updateView(): definitelly when switching back to 2D, but possibly also before feature picking or elsewhere in the wrapper code, if required.

This may bring possible issues for implementation of interaction with ol3 sources, layers, feature picking, etc.

To be discussed here in comments - and on the Monday meeting.

@klokan
Copy link
Member Author

klokan commented Aug 11, 2014

Monday decission: let's go for simple ol.View detaching and Cesium rendering stop.
Then let's create PR with it. Further improvements to be discussed later (after basic PR is merged).
Let's call: map.setView(null);

@petrsloup
Copy link
Member

The problem with this approach is, that after calling map.setView(null), all the ol controls stop working. This would also happen if we were to create a copy of current ol.View (because the controls would be modifying the copy and thus having no effect in 3D).

@klokan klokan changed the title No rendering if invisible & lazy sync Performance: No rendering if invisible & lazy sync Aug 13, 2014
@klokan
Copy link
Member Author

klokan commented Aug 14, 2014

Basic version done with PR #28 - but only on Cesium side.

@ahocevar please comment on possible ideal basic implementation on ol3 side.
Is modification of ol3 for this required?

@ahocevar
Copy link
Member

I think there is no need to change anything in ol3 for this. The following should work:

var view = map.getView();
map.setView(); // pause synchronization
map.setView(view); // resume synchronization

@petrsloup
Copy link
Member

@ahocevar I tried using map.setView(null), but the change of View is propagated to the controls (zoom control and rotation control) and they stop working (see #19 (comment)), although still being displayed.
I expect the exact same thing would happen when calling map.setView() without any parameter, wouldn't it?

@ahocevar
Copy link
Member

Good point @petrsloup. So we need to figure something out on the ol3 side.

@ahocevar
Copy link
Member

In ol.Map, we could introduce a boolean pauseRendering_ property with a setPauseRendering() setter as part of the API. When pauseRendering_ is true, ol.Map#render() will return without doing anything.

@elemoine
Copy link
Member

Controls update their UIs at postrender time. So if the ol.Map#render function returns immediately the controls won't be updated.

@ahocevar
Copy link
Member

@elemoine As far as I can tell, ol.Map#render() is called by ol.Map#renderFrame_(), which dispatches the postrender event. So the controls should still get updated when ol.Map#render() does nothing.

@klokan klokan removed this from the RASTER milestone Aug 18, 2014
@klokan
Copy link
Member Author

klokan commented Sep 16, 2014

OL3 side is not ready for this yet...

@ahocevar
Copy link
Member

@elemoine, any other ideas for fixing this?

@emloux emloux added this to the FEATURES milestone Sep 16, 2014
@klokan
Copy link
Member Author

klokan commented Sep 16, 2014

Lets try to make all the layers invisible on OL3 - and ignore this operation in the synchronizer temporarily on OL3Cesium side (keep list of visible layers separatelly).

@ahocevar
Copy link
Member

Is it possible that there is also a performance penalty of Cesium trying to render the globe while we are viewing the map? Just got this from our client:

When the globe isn't being rendered, it may make sense to stop the animation timer completely. Something like:

this.animationDelay_ = goog.async.AnimationDelay(function() { 
this.scene_.initializeFrame(); 
this.scene_.render(); 
this.camera_.checkCameraChange(); 
this.animationDelay_.start(); 
}, undefined, this);

And call start/stop on the animation delay in olcs.OLCesium.prototype.setEnabled. The timer callback isn't doing much when the globe isn't enabled, but it does still spin the CPU unnecessarily (3-5% usage on my RHEL6 machine on Chrome 35).

When the globe is enabled, is it necessary to render the globe on every frame or can that be managed a little better like the 2D map? I have little experience with Cesium/WebGL so I honestly don't know the answer. My observation was that on Windows there was minor CPU usage (5-7%) even after everything finished rendering and on RHEL6 I was seeing 60-70% CPU usage (on one core) after all tiles were rendered.

@petrsloup
Copy link
Member

The initializeFrame() takes care of camera update and also processes accumulated user interaction events, but in our case we probably don't need to do this when the globe is not visible (it seems the camera is updated automatically when changed, so all the olcs.Camera methods should work properly even without initializeFrame calls) -- I'll look into this.

About the second note (constant rerendering): if we want to automatically "pause" the Cesium rendering, we need to know when the rendering is required (any user interaction, inertial animations, layers changed, tiles loaded, application-specific modifications to the Cesium.Scene (non-synchronized layers, objects...)), but it would be very hard (or impossible) to detect all the possible changes.

@klokan
Copy link
Member Author

klokan commented Sep 22, 2014

Merged is an OL3 implementation which is using the hiding of the root LayerGroup for gaining the performance on OL3 side - this should be acceptable solution for now.

For a more proper solution on OL3 side there may be a new ticket probably.

A comment from @ahocevar in #66:
The only way I could think of for handling this in ol3 would be to give the map a setRenderer method, and create a dummy renderer that does nothing but dispatch render events. The former would be implemented in ol3, the latter could be done on the app (i.e. ol3-cesium) level if we allow applications to subclass ol.renderer.Map and implement renderFrame. Same for ol.renderer.Layer and prepareFrame.

@klokan klokan closed this as completed Sep 22, 2014
@ahocevar
Copy link
Member

Reopening based on feedback from our client:

The globe is no longer rendered when it is not enabled, but I'm still very concerned with rendering the globe on every animation frame. I noticed a significant performance impact when parsing WFS features. Using the 2D map, the application parsed 7000 features in 4 seconds. With the Cesium globe enabled, the same 7000 features took 54 seconds to parse. This is not an acceptable performance hit, and is largely caused by competing resources between rendering features currently on the map and parsing new features.

@ahocevar ahocevar reopened this Sep 24, 2014
@klokan
Copy link
Member Author

klokan commented Sep 24, 2014

This sounds like a problem related to the "Performance of feature synchronizer" - it is probably not as much related to this ticket (which has already 4 pull requests merged). Better to create a new ticket for this @ahocevar?

@klokan
Copy link
Member Author

klokan commented Sep 24, 2014

In fact it seems to me directly related to already open ticket #70.

@ahocevar
Copy link
Member

@wallw-bits @schmidtk Can you please test if #72 fixes this performance issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants