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
Using pre-rendering techniques [$25] #318
Comments
No, Fabric is not doing this kind of caching yet. We tried some optimizations once with complex SVG paths (replacing them with temporary images) but ran into few problems and eventually dropped it. Avoiding rendering of objects that weren't modified could be a great optimization. There are some issues though, like the fact that we would need to mark objects as "dirty" somehow. For example, this wouldn't "work" anymore: object.left = 100; // new value
canvas.renderAll(); // need to mark object dirty before rendering although this could be "fixed" via object.setLeft(100); // object is marked as dirty
canvas.renderAll(); // object is rendered at a new location Would it be OK for objects to behave this way? Even though it's already recommended to use set/get methods to work with properties, I imagine that a lot of people still use plain properties. On the other hand, we can always enable something like this via optional property on canvas! That way we could preserve backwards compatibility. |
For backwards compatibility this should be an opt-in option on the canvas object, and refactoring the code to use the set methods is no problem from what I see. I think this will give a big improvement on the performance of canvas that hold a lot of objects, very complex objects and also it will do a good job for path objects and all transformations done on them. Maybe fabric.Object should have a method 'setDirty()' as well to mark objects for re-rendering if you are running into unusual usage somehow. All of this reminds me of what flex is doing with their framework implementation which keeps rendering cycles and all other computations down to a minimum set needed: http://weblog.mrinalwadhwa.com/wp-content/uploads/2009/06/flex-4-component-lifecycle.pdf |
Feel free to take a stab at it! One problem I can think of is that we'll On Sat, Nov 24, 2012 at 6:46 PM, aggrosoft notifications@github.com wrote:
|
Any updates regarding this feature? Personally, I would really benefit from it, since I am using fabric for editing more 500+ objects. It really starts to be a problem when you drag objects for example. Even though you are dragging only one object, fabric redraws all of them. I could easily live with manually marking objects that do not need re-drawing, and manually un-marking them when once ready. |
@alesdotio Didn't have a chance to do this yet, but also can't wait to get it done already. |
@kangax this would be really useful. I like EaselJS' implementation as it's abstracted away, KineticJS' implementation can be a bit tedious at times. There are plenty of use cases where this would be useful, especially mobile games where performance is very important. I really like Fabric's API, if it had caching as well it would definitely be my go to library. :) |
@jamespacileo I just changed a tag on this ticket from "possible feature" to "feature" :) Can you tell me more about Easel's implementation, or at least point to their docs/source? I'd be curious to get familiar with it. |
@kangax thanks! I'll report back tomorrow! :) |
@kangax here is what EaselJS does each Shape has the following methods The
Once a shape is marked for caching on the next redraw the shape will be drawn to it's own "offscreen" canvas object. On every subsequent redraw the shape will use the image drawn into the offscreen canvas object instead of drawing from scratch. If the cache needs updating The only weakness is that the cache requires the user to manually supply x, y, width, height. FabricJS keeps track of these values so maybe they could be defaulted? Quote from EaselJS docs:
Useful links: |
@jamespacileo Thanks for explanation! This makes perfect sense, of course. Fun fact: we had this functionality back in the days. You can see the "stub" rendering block in an older version of all.js, for example, https://github.com/kangax/fabric.js/blob/a535b004e697f57394d85157e92596fad773d010/dist/all.js#L6623-L6633 The difficulties were with updating cached image when resizing a (vector) shape. At one point, I decided to drop it. This was back in the days when we didn't even have |
@jamespacileo this kind of caching, coupled with dirty-rectangle checking should provide tremendous speed improvements in Fabric |
Will this somehow, improves performance of pen tool on a large canvas ? > 3000px. I am looking for some technical trick, maybe having a dynamicly resizing canvas over topCanvas to receive and draw the pen mouvements. |
Dirty rectangle checking should improve performance in this case. Sent from my iPhone On Jul 20, 2013, at 13:12, coulix notifications@github.com wrote:
|
@kangax awesome, great news! :) Thanks for considering this. I'll be around, contribute more info if I can. |
Hey guys. I'm looking to use Fabricjs for in a scientific computing context, and would be rendering 20,000 items to screen (three layers of graphs, each displaying astronomical spectra). Has there been any update on caching or dirty-rectangle checking for Fabric? I have been able to find this: http://fabricjs.com/svg-caching/, however this is not the dirty update method discussed for this feature request. |
@Samreay Unfortunately, we haven't gotten to these optimization techniques yet. However, if you don't need interaction, it's fairly easy to create 3 fabric canvases overlayed on top of each other. |
Hi kangax. Thanks for the update mate. |
Thank you kangax for your great library! Have you got news for this request? |
I will make sure to update this ticket once there's news |
Is there any news on this request? If not, if you any notes/plans on how you were planning on implementing this then I would be happy to contribute to the project! |
We'll be focusing on performance improvements in the upcoming release. Some things are already in effect — for example, we do itext cursor rendering on a separate canvas. Notes on implementing — hard to tell; these are the usual common techniques used in games, etc. so we just need to adapt them according to fabric's architecture. Any help is welcome of course! |
@kangax , any updates regarding the performance improvements using cache. My application is having performance issues when rendering objects on large canvas. Especially on Chrome with hardware acceleration turned on. There are not a lot of objects on my canvas, my canvas size is 3050px X 3050px. The dragging is very slow and same for mouse clicks. I'm just wondering with caching, it can improve the overall performance. |
with a 9Mega pixel canvas your problem is probably the use of clearRect() for the full canvas. |
I opened a PR to address this. |
closed with #3317 |
Currently the _draw implementation of static canvas will always do a full render of each object - no matter what has been modified. The HTML5 Canvas best practices suggest to render an object only once if you have a lot of render passes and then just draw the bitmap representation if needed - this is equal to what flash does using the cacheAsBitmap property and it's display list .
Without caching:
Using caching:
For Fabric this would mean that the objects manage a property to tell if a redraw is really needed - this could be bound to the stateProperties. Then the static_canvas will use this property to call render or not. After rendering the bitmap will be cached and reused on the next calls.
Maybe I just did not inspect the code good enough, is fabric maybe already doing this?
See:
http://www.html5rocks.com/en/tutorials/canvas/performance/
There is a $25 open bounty on this issue. Add to the bounty at Bountysource.
The text was updated successfully, but these errors were encountered: