vasturiano / force-graph

Force-directed graph rendered on HTML5 canvas
https://vasturiano.github.io/force-graph/example/directional-links-particles/
MIT License
1.54k stars 246 forks source link

Performance problems when overriding linkCanvasObject #93

Open jeffmcwhirter opened 4 years ago

jeffmcwhirter commented 4 years ago

Hi, I am having some really bad performance problems when trying to override the linkCanvasObject method similar to what you have in this example -https://github.com/vasturiano/force-graph/blob/master/example/dash-odd-links/index.html basically: ctx.moveTo(link.source.x, link.source.y); ctx.lineTo(link.target.x, link.target.y); ctx.stroke();

I am using the Les Miserables data (~250 links) and it drags my browser down to its knees. Without overriding this method the graph renders just fine

vasturiano commented 4 years ago

Hi Jeff,

That is most likely because of the canvas stroke instruction that runs at at every link. One thing that you can do is run that instruction only once per frame, on the last link. This will mean all the links will be painted together instead of individually, and should improve the performance dramatically.

Something like:

(link === gData.links[gData.links.length - 1]) && ctx.stroke();

I've applied that fix to the example you mentioned and there is a perceptible performance improvement. https://github.com/vasturiano/force-graph/blob/master/example/dash-odd-links/index.html#L40

jeffmcwhirter commented 4 years ago

Hi Vasco, Thanks for the fix. It works great.

Here is an example of it in RAMADDA - https://geodesystems.com/repository/alias/force_graph_example

-Jeff

On Sun, Jan 19, 2020 at 1:11 AM Vasco Asturiano notifications@github.com wrote:

Hi Jeff,

That is most likely because of the canvas stroke instruction that runs at at every link. One thing that you can do is run that instruction only once per frame, on the last link. This will mean all the links will be painted together instead of individually, and should improve the performance dramatically.

Something like:

(link === gData.links[gData.links.length - 1]) && ctx.stroke();

I've applied that fix to the example you mentioned and there is a perceptible performance improvement.

https://github.com/vasturiano/force-graph/blob/master/example/dash-odd-links/index.html#L40

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/vasturiano/force-graph/issues/93?email_source=notifications&email_token=AANCOTYWE2RCNEWU4R25S7DQ6QDJ5A5CNFSM4KILZ76KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJKLWVA#issuecomment-575978324, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANCOT3FHA5ASXMO2I6P7PTQ6QDJ5ANCNFSM4KILZ76A .

happybeing commented 4 years ago

@vasturiano hope it's ok for me to jump in here. I've been learning to do some basic graph visualisation and began using d3js and trying different implementations (SVG, canvas) to compare performance because I hope to handle relatively large networks at some point.

You can see my first test app here which lets you choose which implementation, and also try out different test data, the default data being Les Miserables.

I stumbled on your work and have been impressed by it, but not tried it out yet. Eventually I want to provide many different ways to view a given dataset through a UI based on Svelte components, so I was planning to come back and look at your 3d and globe.gl visualisations.

Anyway, I just tried the link posted above by @jeffmcwhirter and I'm seeing quite slow redraw compared to all my implementations with this same small dataset. Jeff's example is smoother in Chrome than Firefox (Chrome is much faster than Firefox on mobile and desktop), but my Les Mis graph arranges and drags quite smoothly even on my tablet in Firefox, whereas Jeff's is quite jerky (text or simple nodes).

I'm curious about the difference here - is this just due to customisations made by Jeff? I tried your 1d, 2d, 3d example and it seems fine on my desktop, so I'm wondering what is making Jeff's implementation slower?

I'm designing custom styling for the next iteration right now so interested to learn what is the issue here.

vasturiano commented 4 years ago

@theWebalyst thanks for reaching out.

Are you observing the same slow down in these built-in examples: https://vasturiano.github.io/force-graph/example/dash-odd-links/ https://vasturiano.github.io/force-graph/example/load-json/

happybeing commented 4 years ago

@vasturiano they and the others of yours I've tried have all been fine. It's only Jeff's example that's jittery.

jeffmcwhirter commented 4 years ago

Hummm. I run in it ( https://geodesystems.com/repository/alias/force_graph_example) on a newish macbook (on firefox or safari) and it seems to render fine. I even modified the page to have 2 graphs in tabs and it is fine. Comparing it to the example with the same data (Les Miserables) - https://vasturiano.github.io/force-graph/example/text-nodes/ - the rendering seems the same. They both take about 2 seconds and they both have the same flow

-Jeff

On Mon, Jan 20, 2020 at 2:53 PM Mark Hughes (happybeing) < notifications@github.com> wrote:

@vasturiano https://github.com/vasturiano they and the others of yours I've tried have all been fine. It's only Jeff's example that's jittery.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/vasturiano/force-graph/issues/93?email_source=notifications&email_token=AANCOT6FHQ7YBFAGN32RU3TQ6YMNZA5CNFSM4KILZ76KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJN4VIQ#issuecomment-576440994, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANCOT764GFSV2CWUL4SY23Q6YMNZANCNFSM4KILZ76A .

happybeing commented 4 years ago

@jeffmcwhirter The difference is minor on such a small graph but noticable on lower powered devices (mobile/tablet).

I think to see the difference in desktop you would need a larger graph in a single view. See my example for a way to generate these. Source here: https://github.com/theWebalyst/d3-fdg-svelte-perf

If you play with different graph sizes the live example you'll see how much larger graphs can be rendered before jitter becomes noticable than in your implementation.

FatmaAkram commented 1 year ago

Hi Jeff,

That is most likely because of the canvas stroke instruction that runs at at every link. One thing that you can do is run that instruction only once per frame, on the last link. This will mean all the links will be painted together instead of individually, and should improve the performance dramatically.

Something like:

(link === gData.links[gData.links.length - 1]) && ctx.stroke();

I've applied that fix to the example you mentioned and there is a perceptible performance improvement. https://github.com/vasturiano/force-graph/blob/master/example/dash-odd-links/index.html#L40

I've tried this one, but it only draws the last link. Any thoughts?