Open
Bug 527386
Opened 15 years ago
Updated 2 years ago
Canvas text functions are too slow
Categories
(Core :: Graphics: Canvas2D, defect)
Core
Graphics: Canvas2D
Tracking
()
NEW
People
(Reporter: tthomps, Unassigned)
References
()
Details
(Keywords: testcase)
Attachments
(8 files)
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2b1) Gecko/20091029 Firefox/3.6b1
Build Identifier:
The text functions of the 2d canvas -- measureText, fillText, strokeText, the font property, and drawing text shadows -- do not effectively scale to support drawing a large number of strings on the canvas at once.
I am attaching a page that tests the performance of these canvas functions, and two images of the results on my machine, one for Firefox 3.6b1 and one for Safari 4.
Reproducible: Always
Reporter | ||
Comment 1•15 years ago
|
||
Reporter | ||
Comment 2•15 years ago
|
||
Reporter | ||
Comment 3•15 years ago
|
||
Reporter | ||
Comment 4•15 years ago
|
||
Reporter | ||
Comment 5•15 years ago
|
||
One simple thing that can be done to improve speed is to change the space-replacement function. The current implementation looks like this:
From nsCanvasRenderingContext2D.cpp:
2103 static inline void
2104 TextReplaceWhitespaceCharacters(nsAutoString& str)
2105 {
2106 str.ReplaceChar("\x09\x0A\x0B\x0C\x0D", PRUnichar(' '));
2107 }
It looks like ReplaceChar iterates through every character in the replace string ("\x09\x0A...") for each character in the input string, which is very inefficient.
I think it would be good to use something like this instead:
PRUnichar *c = str.BeginWriting();
PRUnichar *end = str.EndWriting();
for(; c < end; c++)
{
// replace WHATWG spaces, (0x09, 0x0A, 0x0C, 0x0D), with space char 0x20
if(*c >= 9 && *c <= 13) // if we want to include 0x0B
*c = PRUnichar(' ');
}
The above function will replace 0x0B with +U0020 as the current code does, but I do want to note that the HTML5 specification currently doesn't include 0x0B as a character that should be replaced, unless I'm missing something.
Alternatively something like these could be used:
for(; c < end; c++)
{
if(*c == 0x09 || *c == 0x0A || *c == 0x0C || *c == 0x0D)
*c = PRUnichar(' ');
}
Or..
const PRInt32 whatwgSpace [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0 };
for(; c < end; c++)
{
if(*c < 14)
if(whatwgSpace[*c])
*c = PRUnichar(' ');
}
Reporter | ||
Comment 6•15 years ago
|
||
I've only done a simple runtime profile at this point, which is shown in the "Windows profile" attachment. Since it's only a measure of exported functions, it does not give the complete picture of cpu usage here, since a lot of the issues appear to be in internal code. It does look like some functions, such as UpdateFontList, could be improved a bit to gain some speed.
Reporter | ||
Comment 7•15 years ago
|
||
Another thing of note is that when text is drawn with strokeText or with a shadow, the call to Redraw is not given a bounding box for the operation:
2477 if (aOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_FILL && !doDrawShadow)
2478 return Redraw(mThebes->UserToDevice(boundingBox));
2479
2480 return Redraw();
Updated•15 years ago
|
Severity: enhancement → major
Comment 8•15 years ago
|
||
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.4) Gecko/20100413 Firefox/3.6.4
Safe Mode, freshly-open, 1 tab only, XP SP3, AMD Athlon XP 2600+, 1,92 Ghz, 1 GB RAM
Comment 9•15 years ago
|
||
Opera 10.51 results on same machine as above.
Comment 10•13 years ago
|
||
This bug also affects http://kothic.org/js/ in-browser map renderer - it is much slower in Firefox than in any other browser.
Comment 11•13 years ago
|
||
When run in Firefox, KothicJS spends most of its time rendering text on canvas.
The result is ≈5 seconds of additional lag per each OpenStreetMap tile.
Comment 12•12 years ago
|
||
A JS application I’ve made for Chrome is unusable in Firefox due to this problem.
Comment 13•12 years ago
|
||
Jeff, Bas, would you take a look please?
What I see so far on Mac is that the "shadow" case is ludicrously slow...
Status: UNCONFIRMED → NEW
Ever confirmed: true
Comment 14•12 years ago
|
||
On my Mac, every test case is slower in Firefox than Chrome. While the 'shadow' case is some 300 times slower on Firefox, 'strokeText' is still some 17 times slower. 'fillRect' is the only test that gives similar results.
FireFox Mac: 217ms, 1405ms, 737ms, 2720ms, 10670ms, 208ms.
Chrome Mac: 213ms, 571ms, 156ms, 1291ms, 38ms, 13ms.
Comment 15•10 years ago
|
||
All numbers are ms per frame
Nightly 35 (Win 7 - Intel - D3D11 - OMTC - D2D 1.1)
fillRect 1
fillText 47
measureText 16
font Property 71
shadow 365
strokeText 381
Firefox 32 (Win 7 - Intel - D3D10)
fillRect 2
fillText 42
measureText 13
font Property 60
shadow 359
strokeText 356
Chrome 37
fillRect 6
fillText 8
measureText 3
font Property 12
shadow 10
strokeText 8
Chrome 38
fillRect 1
fillText 6
measureText 4
font Property 10
shadow 10
strokeText 7
Comment 16•10 years ago
|
||
On Nightly, at least with the backend on my platform, these numbers are within a few ms of Chrome with the exception of strokeText.
I had a look at resolving that perf issue, but:
CanvasRenderingContext2D.cpp:3492 has a note about CoreGraphics performance requiring individual glyphs to be sent off to the rendering backends (for all backends!), yet removing that and sending the whole buffer made it slower.
Moved on to look at gfx/2d/DrawTargetCairo.cpp and tried cairo_glyph_path with the whole string buffer and that is even slower… it seems like this is blocked by Cairo performance improvements.
Nightly 38 (Linux - nvidia - OMTC-off - cairo)
fillRect 0
fillText 6
measureText 3
font Property 13
shadow 20
strokeText 950
OMTC appears to slow strokeText to ~1400ms
Chrome 40
fillRect 0
fillText 2
measureText 1
font Property 5
shadow 4
strokeText 4
Comment 17•10 years ago
|
||
When I use skia instead of cario(change gfx.canvas.azure.backends), the time of strokeText is boost up.
nightly 39, linux, nvidia, omtc-off
cario:
fillRect 1
fillText 7
measureText 4
font Property 14
shadow 19
strokeText 479
skia:
fillRect 1
fillText 7
measureText 4
font Property 14
shadow 28
strokeText 40
chrome 40:
fillRect 0
fillText 3
measureText 2
font Property 5
shadow 5
strokeText 4
Comment 18•5 years ago
|
||
Performance is still noticeably slower than Chrome: https://jsperf.com/canvas-text-performance
Updated•5 years ago
|
Comment 19•3 years ago
|
||
Here's an anecdotal test: Windows: noticeably
shadow
takes approx 60x times longerstrokeText
approx 25xfillText
/font property
approx 4x
Comment 20•2 years ago
|
||
In the process of migrating remaining bugs to the new severity system, the severity for this bug cannot be automatically determined. Please retriage this bug using the new severity system.
Severity: major → --
You need to log in
before you can comment on or make changes to this bug.
Description
•