-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
free drawing: visible dots with opacity <1 and lag issues #4948
Comments
I just found this: Which already covers the "dots" problem, but doesn't seem to mention the performance issue. |
Can we reproduce the perf problem ? |
I cover it in that last paragraph above ^ Pasting below:
|
I will try to do some more debugging on my end and post my results here |
I have no idea why redwraing just a part shoul be slower than redrawing everyhing everytime, also in your video it happens pretty fast. More than a video, you can just open the chrome dev tools, record the performances, start to draw and wait for the per problem to happen. stop to recording, save the profile and share the profile so i can inspect it. The freeze answer is there. |
I'm not sure what you mean by 'also in your video it happens pretty fast', but if you mean that it is performing normally, maybe you looked at the other video link. Here's the one where it is slow: It's possible that it's not a performance issue at all, but just a code issue with how the line is drawn during mousemove. I'll do some more investigation now, and save a profile... |
After more looking into it, I've sadly discovered that this performance issue is a bug in chrome. Firefox doesn't have the problem, and furthermore the problem goes away in chrome if I disable "Accelerated 2D canvas" in chrome://flags. Furthermore, I'm on linux and I wouldn't be surprised if this is a linux-only issue. I will have to attempt building a minimum testcase and report it at bugs.chromium.org. Thanks. |
Just to document what I did try: As a side note, would it be better to do all canvas drawing inside of a requestAnimationFrame loop? Something like:
... This is an incomplete implementation just to give an idea. I'm wondering if it's better for performance, rather than having drawing code happening inside of mousemove which can perhaps happen more than once per frame. |
having the recorded profile would let you know what is taking too much. |
Here is jsfiddle that reproduces the problem for me: Here is a video showing and explaining the problem (2 minutes): The problem only happens with the css The result on windows is even worse than it is on linux, looks like this (animated gif): |
Chromium bug filed: https://bugs.chromium.org/p/chromium/issues/detail?id=840075 |
Also, just for the sake of comparison here is the same jsfiddle that uses fabric.js v2.0.2: This one works smoothly, because fabric.js v2.0.2 re-renders the entire path on every mousemove which does not trigger the chromium bug. |
I have no idea what trigger the chromium bug, drawing a path or 400 paths, is the same code, the only difference is a clearContext happening. this is a picture of the profile, as you can see there is a frame lasting more than half second that is the moment in which it looks frozen. each mousemove under a long lag of 2 seconds is being executed in 0.24ms that looks good to me. Is not a performance problem, is just a browser bug |
If you want a chance to have the bug looked at, you should reproduce it in plain JS, a bug based on a library is not gonna considered at all. |
@asturur Yes, good idea. I made a pure js one here http://jsfiddle.net/n7nebbL8/16/ |
Another useful bit of info, in case anyone else runs into this same browser bug and finds this github issue later: This means that the bug probably pre-dates the webkit/blink fork in 2013, so it's a long-standing issue. At some point I will file a webkit bug as well. Again, I'll point out: this bug only happens if you're using Unfortunately, in our case |
yes i work on macOS and i could see it. Something you should put the detail on: the more the canvas is resize by css, the more the bug is visible, so if the tester has a big screen ( like a 4k ) and the fiddle does not resize the canvas under 1000px, the bug may not happen. If you use this fiddle in which the container has 100px by 200px container, the bug is immediate and more visible |
Is still unclear to me why our code trigger the bug, but i feel like you may have manymore places in fabricJS that will trigger it. You are triggering with line to, pencilbrush is using quadraticTo, it may happen with more stuff. |
@asturur That's a good note, I will make mention of it on the chromium/webkit bugs and update with the new link Another thing I'll mention: If there is demand for it, I can submit a PR that adds a flag to the fabric.Canvas that allows for toggling of the "clearContext" behavior. It's totally up to you if you want the extra code complexity added for that, just let me know. |
i do not want to work around bugs with patches, they fall forgotten and is not the way things should go. You can patch your application if it has the need to be live with this bug in the wild. Is also unclear why you need the object-fit, you can also work around that resizing the canvas with the container, if you need then a bigger image, you can still make it bigger when you export it. You can work on a 1000px space coordinates on a smaller area using the zoom, and inspecting the container for size and actually resize your canvas instead of css doing it. Performance should benefit too. |
@asturur Yes, I'm worried about this. What this means is that every time I run into the browser bug, I will have to implement some kind of "clearContext-like" patch as a workaround until the browser vendors fix the bug. And that might not even be possible in certain situations! I just don't know the fabric code well enough offhand yet to know for sure if such workarounds will be possible for the other areas of fabric. It's also possible that there's a better workaround for the problem rather than calling clearContext(), but I would have to spend some more time trying to discover that.
In our application, the fabric canvas is overlaid on top of a video element which needs to maintain the aspect ratio when the browser window gets scaled (using And now that you mention it, I'm thinking about this more. I may be able to use object-fit:contain only during rapid "onresize" calls (in order to maintain fast browser window resizes), then remove the object-fit:contain just after all the resizing is totally complete. I already have similar handling in place that changes the backing store dimensions so the canvas is at 1:1 pixel ratio once a window resize is totally complete (so that I avoid having the canvas scaled down). |
Right, I actually already do something like this. the object-fit:contain is to maintain the performance and accuracy (i.e. aspect ratio of the canvas matches the video that it's overlaying) of the canvas when the user does interactive browser window resizes -- I've found that doing canvas backing store resizes in a javascript onresize handler is very slow and even crash-prone. Once the resize operation is totally done, I change the dimensions of the canvas store and reposition/scale the elements appropriately -- I essentially implemented my own setZoom because it gave me a bit more control over some things. |
Yes i normally debounce the resize event, scaling with css while resizing and do the real resize when they mouse up. |
... thankfully I was able to take my existing resize debounce logic and include adding/removing `object-fit:contains' from the canvas as appropriate. So object-fit:contains is now only used during the resize interaction which is fine since the browser bug isn't triggered at that time. Whew! Thanks for the help. |
Version
2.2.3
Test Case
http://jsfiddle.net/uk7jvr6o/12/
Steps to reproduce
Start drawing.
Expected Behavior
No dots along the line, and no performance/lag issues.
Actual Behavior
Dots along the line, and performance/lag issues.
This particular pull request - #4743 - caused two issues that I can notice:
Here is a video of using fabricjs on my project with the latest commit of fabricjs which includes the drawDots PR:
https://youtu.be/wYfd5IohsWY
You can see the performance/lag issue in the video.
The exact "draw dots included" build that I'm using, for reference, is:
https://github.com/AndrewJDR/fabric.js/commits/build_of_a267b76e8
(installed with
npm install 'https://github.com/AndrewJDR/fabric.js#build_of_a267b76e8'
Here is a video of using fabricjs on my project with the latest commit of fabricjs but with the drawDots commit reverted:
https://youtu.be/QQUvphB4sNc
You can observe that there are no dots here, and the performance is fine.
The exact build "draw dots reverted" build I'm using, for reference, is:
https://github.com/AndrewJDR/fabric.js/commits/pencilbrush_drawdot_reverted
(installed locally with
npm install 'https://github.com/AndrewJDR/fabric.js#pencilbrush_drawdot_reverted'
I've included a jsfiddle here where you can easily see the dots:
http://jsfiddle.net/uk7jvr6o/12/
Unfortunately, as for the performance issue (number 2 in the list above), I have not been able to replicate it outside of my web application, which is rather large and there's not a public link of it available at the moment. All I can say is that even with my application, reverting the drawDots PR fixes the performance issue altogether. I know that this is not very helpful at the moment. Perhaps later when I have some more time, I can try to extract enough of my application into a smaller example so I can reproduce the issue. I actually started to do this, but it was getting pretty time consuming. If there's anything less demanding (inserting a few debugging statements, providing some logs, checking something in the webdev console, etc) that you can suggest in the meantime to try to track it down, I'd be happy to help with that.
For now, on my end I'll be running a fork of fabric.js with this drawDots commit reverted.
The text was updated successfully, but these errors were encountered: