gereleth / hexapipes

Hexagonal pipes puzzles
https://hexapipes.vercel.app/hexagonal/5
MIT License
187 stars 19 forks source link

Performance issues on mobile device #14

Open YesSeri opened 2 years ago

YesSeri commented 2 years ago

I really like this game. Great execution and a great idea. Is it your idea originally?

It works great at 5x5, with no performance issues. At 10x10 it is lagging a little, and at 40x40 it is really slow. At 40 it takes about one second for the hex to turn every time I press.

I am using a Samsung Galaxy s20. It is a mid or high end phone, two years old.

I can't promise anything but do you want me to look into the code and see if it can be optimised?

Do you have any thoughts as to why it is slow?

gereleth commented 2 years ago

Square grid pipes puzzles have existed for a long time. I'd say my original contributions were the hex grid and the way connected groups get different colors. I haven't seen edge marks implemented anywhere else either.

Performance issues probably come from manipulating a huge svg with a ton of inner elements. On my moto g7 I don't quite see a whole second lags on a 40x40 board but I agree that the game becomes visibly less snappy as the size grows.

When playing a large puzzle on mobile you'll normally be zoomed in and only see a small portion of the board at a time. So maybe it would be faster if we only render the currently visible portion. There is some prep work done for this in how wrap puzzles handle zoom in/out, i.e. there's a method on grid to get currently visible cells. But there's a lot of details to think about with this approach, like how to reconcile moving around the page and moving around the board.

I've also been experimenting with rendering to canvas instead of svg (here's an example repl). This might be faster still but there's a whole lot of stuff to redo with this approach...

Please feel free to report any other possible optimizations that you notice.

YesSeri commented 2 years ago

I haven't been able to find anything super obvious, but I have only looked for 30 min. I think you are right that canvas is the way to go, if you want better performance.

Pyrolistical commented 2 years ago

My gut says its not rendering that is the problem, its the game logic. It seems to slow down for me even on desktop when two large networks are about to be colored the same. This happens a lot as the last move of a game.

I suspect the algorithm to color the network is taking longer than 16ms. If that is indeed the case, we can break up that work into smaller parts to prevent frame drops, move it into a worker, or heck implement the core algorithm in web assembly.

But I do lack information. It could be rendering issue after all. I'm just guessing.

gereleth commented 2 years ago

A slowdown happening on desktop doesn't really rule out rendering performance problems =). The game still has to recolor a few hundred svg paths on that last move.

I'm working on improving game controls over in #34 It's possible to zoom in and pan the game area there, and only the currently visible tiles are rendered. You can try it out in the pull request - look for a "Visit preview" link there.

It would be interesting to check if you still see the same lag when solving a 40x40 while zoomed in. There will be less stuff to render so any lag remaining must be due to game logic inefficiencies.

gereleth commented 2 years ago

Hi @YesSeri

I've published the zoom and pan changes so now you can solve a big puzzle while zoomed in and the game will only render the tiles you're looking at. Does this help with performance problems you mentioned?

YesSeri commented 2 years ago

It is a lot better now! Thank you!

Pyrolistical commented 2 years ago

I'm still having performance issues on my old iMac. It runs fine on iPhone 12 and M1 MacBook Air.

I think it is likely to do with https://github.com/gereleth/hexapipes/blob/95c1db4def7255f740894631fbec2c97f8aa220f/src/lib/puzzle/Puzzle.svelte#L178

While panning/zooming, the grid has to recalculate the visible tiles and the svg is re-rendered the visible tiles.

The more performant is to render all the svg tiles once and panning/zooming only changes viewBox. The memory usage of offscreen svg tiles should be negligible.

This would each tile state change more expensive as it would iterate over offscreen tiles as well, but it might not be an issue and even if it is slower, it is not during a a performance sensitive time as panning/zooming is.

I'll measure the time taken of the existing visible tile behaviour to see if my theory holds water.

gereleth commented 2 years ago

The way things work right now is:

How do these performance issues look? Maybe panning seems slow because the normalizeWheel package isn't doing a good job translating your trackpad gestures into wheel events - reporting too small movements perhaps. Could you do a click and drag action to pan and tell me how that compares to panning with a two finger swipe?

Pyrolistical commented 2 years ago

Here is a single render captured by Chrome Dev tools.

Screen Shot 2022-08-13 at 3 39 55 PM

It is indeed using keyed update, but definitely re-rendering about 160 tiles on each mouse movement. The tiles are the ones that become visible at the edges and since my desktop is really slow, it takes about 1 ms per tile (lmao). So then it janks.

When I zoom out all the way and all tiles are visible, panning performance is much better as no tiles are re-rendered.