anvaka / ngraph

Beautiful Graphs
MIT License
1.43k stars 131 forks source link

Move layout functions to Web Worker for pixi.js examples #20

Closed gouldingken closed 9 years ago

gouldingken commented 9 years ago

I saw you mentioned in another issue that you were planning to move some functions to web workers in one of the other threads. This seems especially important for the pixi.js examples where layout is currently being done in the render loop.

I don't know if you've tried this yet, but I did a quick test of putting the layout function in a web worker. I don't have any performance comparisons, but I'm doing some more graphically intensive stuff in Pixi.js so I'm getting about 18 fps on the render loop. The layout loop on the worker is running at around 40fps. This ensures a much quicker (and consistent) layout resolution time while still keeping a reasonably smooth graphics performance. Its working well enough that I thought it was worth posting an issue here. I can extract and share the relevant code if that's helpful.

anvaka commented 9 years ago

Very interesting! Do you have an example to share?

gouldingken commented 9 years ago

Yes. Actually I tweaked it some more and it's up to 100 layout cycles per second. It seems the amount of data sent between the threads matters. I have one more optimization to try then I will push it to git and share with you -hopefully tomorrow as it's getting late here EST.

Thank you so much for your work on this. The modularity and speed are a game changer for me. I've used d3 and sigma for a while now but have always been limited by the number of nodes I can show and have had to resort to Java (GephiLib + Processing) to show real time visualizations.

I'm very excited about the potential of ngraph plus pixi! On Sep 11, 2015 11:29 PM, "Andrei Kashcha" notifications@github.com wrote:

Very interesting! Do you have an example to share?

— Reply to this email directly or view it on GitHub https://github.com/anvaka/ngraph/issues/20#issuecomment-139706124.

gouldingken commented 9 years ago

Here's the example: https://github.com/gouldingken/pixi-ngraph

anvaka commented 9 years ago

Thanks for the demo!

I forked you repository and extracted web worker code into plain javascript file to compare FPS of the two approaches.

To get accurate FPS measures I'm using built-in tool inside Chrome: Dev tools -> then press ESC key to bring up a drawer from the bottom and -> Click Rendering tab and select "Show FPS meter":

image

https://anvaka.github.io/pixi-ngraph/index.html - this is unmodified version with layout inside web workers https://anvaka.github.io/pixi-ngraph/index-plain.html - this version computes layout inside requestAnimationFrame()

I couldn't see much difference between them, but maybe I'm missing something. Do you get better results on your end?

gouldingken commented 9 years ago

Thanks for putting those comparisons together. Yes I see a huge difference! In the second example, it takes a full minute for the layout to fully resolve (1000 cycles). In the first example it takes less than 8 seconds!

In both cases the FPS will be about the same because that's just measuring the render cycles.

The problem I'm trying to solve is that I want my users to be able to see (and start interacting with) the final layout a lot more quickly. I don't want them waiting a full minute for it to get to that point while they watch things slowly laying out.

stevenalowe commented 9 years ago

Fwiw the layout with web workers is much smoother and seems faster on iPhone safari

--S

On Sep 13, 2015, at 3:58 PM, Andrei Kashcha notifications@github.com wrote:

Thanks for the demo!

I forked you repository and extracted web worker code into plain javascript file to compare FPS of the two approaches.

To get accurate FPS measures I'm using built-in tool inside Chrome: Dev tools -> then press ESC key to bring up a drawer from the bottom and -> Click Rendering tab and select "Show FPS meter:

https://anvaka.github.io/pixi-ngraph/index.html - this is unmodified version with layout inside web workers https://anvaka.github.io/pixi-ngraph/index-plain.html - this version computes layout inside requestAnimationFrame()

I couldn't see much difference between them, but I maybe I'm missing something. Do you get better results on your end?

— Reply to this email directly or view it on GitHub.

gouldingken commented 9 years ago

Thanks Steven. I hadn't thought to try it on mobile. FWIW I just tried on my old HTC and it renders at around 4fps, but lays out at around 20 loops per second. It's not fast by any measure, but the difference between the 2 methods is accentuated.

anvaka commented 9 years ago

Ah, thanks for the clarification. I see a lot of value in your use case.

I'm going to create a force layout wrapper to perform computation in the web worker if possible.

PS: Regarding

I saw you mentioned in another issue that you were planning to move some functions to web workers

I was trying to optimize FPS, not number of iterations, when I made this experiment 6 months ago. But your idea makes much more sense!

gouldingken commented 9 years ago

Thanks Andrei.

anvaka commented 9 years ago

https://github.com/anvaka/ngraph.asyncforce here is a first draft. Please take a look. Not sure if I like the API...

gouldingken commented 9 years ago

This looks great. I like that you've included ways to communicate pinning and other options across to the layout worker.

One thing I don't really understand is why you are calling layout.step(); within the render loop. Why is this necessary? Can the layout not just keep looping of its own accord?

Thanks for all your work on this.

anvaka commented 9 years ago

There are couple reasons:

  1. When you execute everything in the web worker - it doesn't know when your page is not active. Thus it keeps running CPU intensive computation even when you look at something else. This will quickly kill a battery on laptop or mobile device. By having step() operation you are giving worker a hint, that page is still active.
  2. I wanted to make it backward compatible with regular ngraph.forcelayout.

If you don't like this behavior but prefer to compute N iterations of layout, you can tweak waitForStep option. See full example here: https://github.com/anvaka/ngraph.asyncforce/blob/master/demo/vivagraph/index.js#L19