lightbeam-we
lightbeam-we copied to clipboard
[WIP] Introducing web workers
This is an initial attempt to improve the graph's performance for large no. of nodes.
Issue #232
The idea in this PR is to off-load the heavy force layout computations to the web worker. This improves performance during page load.
I am also experimenting on passing the logic to web workers during the drag events. This part is still work in progress.
Here is the rough idea that I try to achieve:
In the present situation, when we drag, the force layout restarts the simulation. When there are large no. of nodes, the graph takes a lot of time to achieve equilibrium, thereby dropping the frame rates. Restarting the simulation is necessary, to compute the updated coordinates and give the soft transition, else the drag effect doesn't appear smooth.
Using web workers, I try to keep the dragged coordinates in the main thread, invoke the web worker during dragEnd
. The web worker computes the updated coordinates and waits until the graph attains equilibrium. I need to figure a way to get the updated coordinates and achieve smooth animations.
cc @jonathanKingston @biancadanforth
I think this is a cool experiment but I actually think a lot of the perf improvements could be improved in the main thread first which I did in #232. I can't remember the line of code but essentially I just reduced the large amount of recalc.
@jonathanKingston
I think, you commented out the manualTick()
and things still looked good. But there are other use cases and now that I understand how alpha
really works, I shall try to explain them below.
simulateForce() {
if (!this.simulation) {
this.simulation = d3.forceSimulation(this.nodes);
this.simulation.on('tick', () => this.drawOnCanvas());
this.registerSimulationForces();
} else {
this.simulation.nodes(this.nodes);
}
this.registerLinkForce();
this.manualTick();
}
- The simulation is initialised with
d3.forceSimulation(this.nodes)
. - Default value of
alpha
is1
. - The
tick()
runs fromalpha=1
toalpha=0
. - The graph achieves equilibrium when
alpha=0
. - At each
tick()
the graph updatesx, y, vx, vy
for each node, by adhering to the registered forces.- Example: The updated
x, y, vx, vy
shouldn't result in a collision and this it takes care by making sure thecollisionRadius
is applied.
- Example: The updated
The tick function increments the current
alpha
by(alphaTarget – alpha) × alphaDecay
; then invokes each registered force, passing the newalpha
; then decrements each node’s velocity byvelocity × velocityDecay
; lastly increments each node’s position by velocity.
Case 1: Page Load
-
this.manualTick()
is unnecessary. - The
tick()
runs fromalpha=1
toalpha=0
. - User sees animation with updated node coordinates and graph comes to stop when
alpha=0
.
Case 2: Add new nodes (alpha
is still not 0
)
- Meanwhile, if new nodes are added, and the graph has still not achieved equilibrium (from the page load), then we get the right graph, i.e. simulation still tries to accommodate the newly added nodes and apply the registered forces via the
tick()
function. - The graph along with these newly added nodes are centered w.r.to to the display area, collision has been resolved etc.
Case 3: Add new nodes (alpha
is 0
)
- When the graph has cooled down (
alpha
=0
), and when new nodes come in, then these newly added nodes appear on top left. - This is because, the
tick()
function has stopped. - The
tick()
function only runs foralpha
ranging from1
to0
. - I didn't know the internals and this is why I had added
manualTick()
initially.
Next Steps:
- One way to accommodate new nodes when
alpha=0
is to restart the simulation. - i.e. Reset the value of
alpha
in the range[1,0]
andsimulation.restart()
. - Mere restarting the simulation without resetting alpha has no point because the
tick()
function will not run ifalpha=0
. - Resetting the
alpha
and restarting the simulation makes thetick()
function run and we again get the right graph. - But when the graph has lot of nodes, as reported in #232, this reset and restart will get expensive, as the graph tries to adhere to all the registered forces and as a result, the animations will constantly slow down the graph, thereby making it extremely difficult for interactivity.
- This is the main motivation to add the web worker approach.
cc @biancadanforth
Debugging the ALPHA! :)