Closed Shiuyin closed 3 years ago
What was the code to render the text?
Basically it boils down to these:
// 1st attempt: Regular text() element
// rowGroup.text(cell.label).move(currentX, y)
// 2nd attempt: Regular plain() element
// rowGroup.plain(cell.label).move(currentX, y)
// 3rd attempt: vanilla js
// const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
// text.setAttribute('x', currentX.toString())
// text.setAttribute('y', y.toString())
// text.setAttribute('fill', '#000')
// text.textContent = cell.label
// const svgEl = document.getElementById(id)
// svgEl.appendChild(text)
These are simply called in a loop of those 1200 strings to display.
Replace move
with amove
and you should see a dramatic speedup.
svg.js positions the text by its upper left corner (as any shape) and NOT its baseline. Thats why the bbox call is needed (which is really slow). amove()
will instead position the text by just setting x and y (so by its anchor and baseline) and therefore is faster
That actually helped quite a lot. Thank you. We are now down to 5s for 1200 text() elements and about 0.5s for 1200 plain() elements. So the plain() element is pretty close to the vanillajs but still about 50x slower. Are there any further recommendations you have to improve the performance for large svg's with thousands of text elements?
You will never achieve the same performance. svg.js allocates objects, calls functions, checks multiple inputs and so on. Instead of amove you can just use attr which saves you one call but that wont do much. If you need performance, create yourself a helper function that uses vanillajs for the heavy lifting and adopt the elements with svg.js later
Ok. Thank you for your answers.
We have done some performance analysis when using svg.js text() or plain() elements.
When creating 200 nodes and 6 text() elements per node (=> 1200 text() elements), svg.js takes about 11s to render. This is in an empty side. In contrast using the plain() element, this takes just about 4s. Both take way to much time tho as the vanilla js implementation is done in about 0.01s.
From what we can tell there is a lot of time used in getBBox() and a lot of extra magic going on with newlines, etc. Is there a way to improve this performance to be able to support thousands of text elements and still get usable performance?
Attached you can find the dump of Chrome's performance profiler for both cases.
svg_text_performance.zip