Draft: Parallelised geometry update
Continuing in the same vein as !4963 (merged), this MR parallelises the Drawing:update()
function for a significant speedup on zoom/rotate of update-heavy documents.
A good example of the improvement is National_Grid_drawing.svgz, which goes from pretty chuggy to almost smooth (on a debug build).
Parallelism is achieved through OpenMP tasking, which internally uses a nice work-stealing scheduler to dynamically balance the workload between cores. (The only other widely-used library with a work-stealing scheduler is Intel TBB, which has an incompatible licence, and I don't want to have to write my own, so OpenMP it is, even if it's a Fortran hack. It's also already in use in Inkscape, so there's that.)
A heuristic based on the number of children (including clip/mask/pattern children) is used to selectively turn on parallelism only for heavy nodes. On the first run, when this information isn't available, a simpler heuristic based on the number of direct children is used instead, to avoid the first run being slow.
Certain modifications that occur during updating (namely, manipulating the cache and invalidating the canvas) are no longer safe to perform during update due to their modification of shared state, so these are stuffed into thread-local Util::FuncLog
s instead and executed at the end when it is safe to do so (i.e. it's another deferral system, like in !4876 (merged)). Note that a mutex would not have been a good solution here, because invalidations can be generated at extremely high volume.
I've also thrown in an extension of the is
/cast
system from !4760 (merged) to DrawingItem
, because I saw more dynamic_cast
s in update and render functions than I liked - sometimes more than one per node. There's also a mostly typo-fixing commit for the LPE test.
#ifdefs
instead.)