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

Debounce map to screen #414

Merged
merged 7 commits into from
Aug 12, 2017
Merged

Debounce map to screen #414

merged 7 commits into from
Aug 12, 2017

Conversation

jameshadfield
Copy link
Member

@jameshadfield jameshadfield commented Aug 2, 2017

This PR closes #387

The timings (see PR #413, which this branches off of) for a single tick (averaged for 10 ticks, 3 runs) are as follows:

flu (http://localhost:4000/flu/h3n2/ha/6y?c=region&dmax=2017-04-24&dmin=2013-09-02&r=country)

  • TreeView: 60ms -> 23ms (around 17ms when averaged over 100 frames)
  • (for reference: Map: c. 7.5ms - demes only, no transmissions)

zika (http://localhost:4000/zika?dmax=2017-04-17&dmin=2015-08-13)

  • TreeView: 5.53ms -> 3.96ms
  • (for reference: Map: c. 10ms)

These measurements are based off a debounce time of 200ms, however this is easily changed. 500ms seemed to have no real change.

The debounce ensures that the final mapToScreen call will go through - important for when the animation is paused.

@trvrb
Copy link
Member

trvrb commented Aug 3, 2017

@jameshadfield ---

I didn't realize this was such a simple bit of code. It's working at least in terms of speeding up tree drawing. However, by messing with the date slider a bit I can very easily confuse the debounce and end up with a tree that has not had mapToScreen run on it and so it has overhanging branches.

maptoscreen

Ah! Here's the issue (I believe): mapToScreen is properly fired at the end of the debounce. However, this is not tied to a tree redraw. So the internal geometry is updated, but the SVG is never updated.

I was thinking to do this a bit differently involving a quickdraw state in redux that would be triggered while any date manipulation occurs. During this quickdraw state, mapToScreen is skipped. quickdraw state would turn itself off if date slider is not touched for 500ms. When it does so a tree redraw would be triggered (or really any component listening to this redux state would rerender). I was thinking this would be extensible to other heavy functions we have that we'd want to skip over when favoring draw performance. Each component could decide to rerender differently if quickdraw is on (or not and just render the same regardless).

@jameshadfield
Copy link
Member Author

Let's discuss today -mapToScreen is a method* inside PhyloTree so this would need to modify how TreeView calls PhyloTree in order to allow a "quick" update. This advantage would be that more things than mapToScreen could be debounced, as we deem necessary through performance testing.

@jameshadfield
Copy link
Member Author

jameshadfield commented Aug 4, 2017

@trvrb @colinmegill do we want
(A) a redux flag during animation (or other high compute phases) which tells each component to throttle / debounce expensive functions
or
(B) a PhyloTree debounced mapToScreen with correct post-run-rendering
???

@jameshadfield
Copy link
Member Author

jameshadfield commented Aug 4, 2017

Now implemented with redux.controls.quickdraw which is designed to allow each component to render appropriately when the app is in a quickdraw state.

Currently, TreeView skips the mapToScreen() resulting in the following tick-timings (when averaged over 50 ticks):

@jameshadfield
Copy link
Member Author

@trvrb i think this is finally working as we would like - please give it a test

As we move forward, more components can listen to state.controls.quickdraw and adjust their rendering accordingly.

@trvrb
Copy link
Member

trvrb commented Aug 8, 2017

Thanks @jameshadfield! I'll check this out.

@@ -273,6 +273,7 @@ export const salientPropChanges = (props, nextProps, tree) => {
const branchThickness = props.tree.branchThicknessVersion !== nextProps.tree.branchThicknessVersion;
const layout = props.layout !== nextProps.layout;
const distanceMeasure = props.distanceMeasure !== nextProps.distanceMeasure;
const rerenderAllElements = nextProps.quickdraw === false && props.quickdraw === true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had been imagining this as running rerenderAllElements from a particular action that fires when toggling from quickdraw=true to quickdraw=false. I agree with this setup however.

@trvrb
Copy link
Member

trvrb commented Aug 12, 2017

Went through the code here. Looking really good.

  • I confirmed that quickdraw state in redux is behaving appropriately via redux dev tools and via console logs. Could not break this.
  • I confirmed that the final rerender is always happening to the tree.
  • With this in place I'm getting a 5-7ms updateMultipleArray for Ebola during animation ticks. On current master I'm getting 24-30ms updateMultipleArray. Nice improvement.

For simpler React components they can just listen to this.state.controls.quickdraw and the flip in redux will trigger a component rerender. Should be easy in this case. I think this part should work well moving forward.

Thanks for getting this together @jameshadfield!

@trvrb trvrb merged commit 845159b into master Aug 12, 2017
@trvrb trvrb deleted the debounce-map-to-screen branch August 12, 2017 07:12
@jameshadfield
Copy link
Member Author

great. One thing for us to remember is that rerenderAllElements is a bit of a misnomer as it only rerenders certain attributes & styles. If we make PhyloTree skip more steps during a quickdraw we have to remember to add them to this method as well.

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

Successfully merging this pull request may close these issues.

Debounce or otherwise improve mapToScreen
2 participants