Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

High CPU load with many canvases #25

Closed
shepelevstas opened this issue Apr 24, 2020 · 7 comments
Closed

High CPU load with many canvases #25

shepelevstas opened this issue Apr 24, 2020 · 7 comments

Comments

@shepelevstas
Copy link

shepelevstas commented Apr 24, 2020

When I get ~100 canvases on page and change something on one of them, all canvases are redrawn.
If this change is something intensive as mousemove, the CPU load jumps and stays high until I stop changing the canvas.
Is it possible to not redraw canvases for which draw commands did not change? Will commands diffing in set cmds (values) be less CPU-intensive than redrawing?

@shepelevstas
Copy link
Author

I experimented a bit, changed set cmds(values) in elm-canvas.js to this:

set cmds(values) {

        if (this.commands.length !== values.length){

          this.commands = values;
          this.render();

        } else if (
          values.some((cmd,i)=>{
            const _cmd = this.commands[i]
            if (cmd.type!==_cmd.type) {return true}
            if (cmd.name!==_cmd.name) {return true}
            if (cmd.type==='function'){
              if (cmd.args.length!==_cmd.args.length) {return true}
              for (let a = 0, l = cmd.args.length; a<l;a++)
                if (cmd.args[a]!==_cmd.args[a]) {return true}
            } else if (cmd.type==='field') {
              if (cmd.value!==_cmd.value) {return true}
            }
          })
        ) {

          this.commands = values;
          this.render();

        }
      }

and removed this.commands = []; from render()
with 80+ canvases on page mouseover-changes reduced cpu load from ~26% to ~12% =D
comparing draw commands are ~2 times easier to do!

@shepelevstas
Copy link
Author

I guess this is unnecessary with Html.Layz and Html.Keyed?

@joakin
Copy link
Owner

joakin commented Apr 30, 2020

When I get ~100 canvases on page and change something on one of them, all canvases are redrawn.

Wow. Regardless of the rest, why would you want to have 100 canvas at the same time on the page? 😛

If this change is something intensive as mousemove, the CPU load jumps and stays high until I stop changing the canvas.
Is it possible to not redraw canvases for which draw commands did not change? Will commands diffing in set cmds (values) be less CPU-intensive than redrawing?

To avoid redrawing elements and this canvas as well use Html.Lazy and Html.Keyed like you said below.

I wouldn't recommend patching the JS library with random things, the design of it is very coupled to the Elm library 😃

@joakin joakin closed this as completed Apr 30, 2020
@shepelevstas
Copy link
Author

shepelevstas commented Apr 30, 2020

I'm working on a service for photo printing shops, customers load their photos online and crop them as needed, they can load tens and sometimes hundreds of pictures, and they can not go cropping them one by one, they need to see them all at once, see the cropping for standard print sizes and be able to correct them with minimal effort =)

@shepelevstas
Copy link
Author

shepelevstas commented Apr 30, 2020

Html.Lazy and Html.Keyed works great! But canvas get redrawn even if nothing drawn to it changed when just style "cursor" is changed based on mousemove position.

@joakin
Copy link
Owner

joakin commented May 1, 2020

I'm working on a service for photo printing shops, customers load their photos online and crop them as needed, they can load tens and sometimes hundreds of pictures, and they can not go cropping them one by one, they need to see them all at once, see the cropping for standard print sizes and be able to correct them with minimal effort =)

You do you but maybe using DOM images and an SVG rectangle on top to show the crop, or a wrapping div with overflow hidden is what I would do and I would crop things only once in the backend when submitting the pictures and the cropping rectangle as data. But anyways there are many ways to do this 😋

Html.Lazy and Html.Keyed works great! But canvas get redrawn even if nothing drawn to it changed when just style "cursor" is changed based on mousemove position.

If that is something that is breaking your optimization, try wrapping the lazy thing with a dom node that has the style cursor and inside it you have the Html.lazy with the canvas, that way the canvas parameters don't change because the cursor logic is outside (and I think cursor applies to nested DOM elements).

@shepelevstas
Copy link
Author

img + svg or couple of divs with hidden overflow is probably a better way. For three or so days I've been working on implementing it in the form of a customElement, but I guess I need to study elm and it's js interop more to finish it. I'm planing to study elm-canvas and how it sends render comands to the custromElement (the only way to send info to customElement from elm that I know is through element attributes, and I didn't find it in elm-canvas=))
Thant's a good idea to wrap canvas with cursor style dedicated element! Thanks you! I'll try it!=D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants