mozilla / lightbeam-we

Web Extension version of the Firefox Lightbeam add-on
https://addons.mozilla.org/en-GB/firefox/addon/lightbeam/
Mozilla Public License 2.0
180 stars 61 forks source link

[WIP] Introducing web workers #233

Open princiya opened 6 years ago

princiya commented 6 years ago

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:

drag

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

jonathanKingston commented 6 years ago

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.

princiya commented 6 years ago

@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 tick function increments the current alpha by (alphaTarget – alpha) × alphaDecay; then invokes each registered force, passing the new alpha; then decrements each node’s velocity by velocity × velocityDecay; lastly increments each node’s position by velocity.

Case 1: Page Load

Case 2: Add new nodes (alpha is still not 0)

Case 3: Add new nodes (alpha is 0)

Next Steps:

cc @biancadanforth

princiya commented 6 years ago

Debugging the ALPHA! :)

d3 force layout_1