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 when IText element selected - bug? #2016

Closed
ajck opened this issue Mar 5, 2015 · 14 comments · Fixed by #2065
Closed

High CPU when IText element selected - bug? #2016

ajck opened this issue Mar 5, 2015 · 14 comments · Fixed by #2065

Comments

@ajck
Copy link

ajck commented Mar 5, 2015

Hi,

Creating this issue as per @kangax request in this post: https://groups.google.com/forum/#!topic/fabricjs/erhDXOq1EWQ

I'm seeing high CPU usage that remains high for no apparent reason even if there's no activity, on a browser process when there's a Fabric IText element on the page that's in edit mode, i.e. double clicked so flashing cursor appears, or double-clicked and dragged so a portion of text is hilighted. So long as the element remains in that mode (i.e user doesn't click elsewhere on the actual Canvas to deselect the IText element) and even if there is no other user activity or visible browser activity, CPU usage just sits high, computer fan comes on stronger and stronger. Tested in latest Chrome (CPU usage hovers around 50% just for that one browser window), latest Firefox (somewhere between 25 and 50%), latest Opera (40ish %) and unexpectedly a bit lower in IE 11 (about 15 - 25%). I'm running Windows 7, 32 bit, if that makes any difference...

You can try this in the kitchensink demo but it also applies on a very simple demo canvas with a single IText element with "hello world" in it.

Is this a bug? It should be :) I can understand high CPU usage potentially for moving objects around or other processing, but not just a selected IText element apparently doing nothing.
(Note this doesn't happen when it's single-selected so that handles are visible).

Kangax says in above linked thread that it's because entire canvas is re-rendered during cursor-tick. I am happy for cursor tick to be switched off (e.g. static but visible) if that helps!

Thanks,
Alex

@kangax
Copy link
Member

kangax commented Mar 5, 2015

Btw, there's a good chance #1979 could help with that /cc @jagi @gordyr

@asturur
Copy link
Member

asturur commented Mar 5, 2015

I 'm not so high with cpu. i m around on 5 - 6 % that on a quad thread machine means 25% of a core more or less.

Anyway i think is just cursor animation.... could it be?

@gordyr
Copy link
Contributor

gordyr commented Mar 5, 2015

@ajk this will be because of the flashing cursor.

When using IText the scene has to be continuously redrawn since the cursor is flashing. (I believe... At least this was the case about a year ago when I was playing with fabric, things may have changed since then)

In which case using requestAnimationFrame as suggested by @kangax will help dramatically.

However.... I think we should look at moving the cursor and text selection rendering onto a separate canvas. This way the whole background can remain static and any cursor/selection manipulation is rendered separately on its own. This would dramatically speed up such operations and provide a far more responsive experience. This is one of the many hacks I have applied myself in my application by overwriting various fabric functions and it works extremely well.

That being said... It is a long time since I poked around the source for the current version of fabric so much of the internals may have changed.

@ajck
Copy link
Author

ajck commented Mar 5, 2015

Thanks all. (Disclaimer: I'm an experienced coder but relatively new to front end web/JS/DOM/Fabric).

Anyway, my needs are very simple, just a single canvas on a page, between 1 and a few iText elements will be present, only 1 needs to be active at any one time. It does need to be active for editing tho, so user can just start typing when page loads rather than have to click in the right place first.
But ideally a single flashing cursor on a page shouldn't be causing 50% CPU load :) - personally I have no need in my web app for animation, 60 (or even 30) FPS, etc. so any static or blinking cursor (doesn't have to fade) that indicates to the user they can start typing is fine by me :)

FWIW my laptop's dual Pentium T3400 @ 2.16 Ghz, 2.5 GB ram, Win 7 32 bit. So not super powerful. But I am aware my app will be run on many older machines, and smartphones and tablets of lesser power!

Not sure how to implement rAF in my (very simple) code...?

Thanks!

@gordyr
Copy link
Contributor

gordyr commented Mar 5, 2015

@ajck Theres a little snippet I quickly wrote on the thread that @kangax posted. Just add it into your code and it should overwrite the needed parts of fabric. As I mentioned in that thread, I haven't tested it fully so it's possible there could be some edge cases I'm not aware of.... But anyway it should at least give you a start.

The truth is however that although this should help dramatically (by preventing the scene from attempting to draw more frequently than the CPU can handle) the real answer is to move the cursor onto a separate canvas so that the scene doesn't have to be redrawn ever frame. That would drop your CPU usage down to literally next to nothing.

Redrawing a tiny few pixels should not need to invalidate the whole scene. I'm sure @kangax won't mind me saying..... I love his library so much... but this decision was a bit daft :P

I'm busy right now but If I get a chance across the next week I'll tidy up my hack for doing this and post it here, or better yet create a PR.

@asturur
Copy link
Member

asturur commented Mar 5, 2015

Itext in general was ( and mostly is still ) a little be in draft mode.
Consider that there was a double redraw of the scene to avoid some visual bug when changing fonts bolds or other things.
Moving the cursor outside to another canvas is for sure something to do.

@asturur
Copy link
Member

asturur commented Mar 30, 2015

PR #2065

@fenderle
Copy link

I still see high cpu usage while IText is active. Is it possible to disable the fading in the animation?

@asturur
Copy link
Member

asturur commented May 24, 2016

On latest version on current github we are not clearing anymore the full canvas but just the itext area part of the canvas. That should help a bit. Do you wanna give it a shot?

@fenderle
Copy link

fenderle commented May 24, 2016

The CPU Load is gone. However the cursor also stopped flashing (I don't care, just wanted to mention it)

EDIT: The CPU load is still there. When I activate the edit mode Chrome goes up to ~50%. The cursor however does not flash (as mentioned above).

@asturur
Copy link
Member

asturur commented May 24, 2016

what cpu do you have?

@fenderle
Copy link

Ok - the non-flashing cursor was my fault. It does flash, I just had the renderCursor function overloaded with a patched version to fix the scaling bug when using viewportTransform. However I noticed that I only see the cursor flashing when I have an angle > 0 on the Textbox. angle == 0 and you see no cursor, but this is possibly related to the viewportTransform, too.

When I comment the clearRect/fillRect calls in renderCursor the CPU load drops to the normal level. Activating one or the other or even both functions brings Chrome up to ~50%.

I have a Macbook pro Retina with an i5 and I currently use the Retina screen (so HiDPI)

@fenderle
Copy link

Chrome and Firefox both show the same behaviour. I appended a profiler output for each browser while the Textbox is in edit mode, flashing the cursor. Each run was around 10sec.

profiles.zip

@asturur
Copy link
Member

asturur commented May 30, 2016

i just pushed another pr, removing the request animation frame under certain condition and avoiding to redraw when is not necessary. i do not see any other easy optimization.

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

Successfully merging a pull request may close this issue.

5 participants