Open Bug 722090 Opened 11 years ago Updated 2 months ago

JS animations of the 'transform' attribute in an SVG slide show causes lots of expensive invalidation


(Core :: SVG, defect)

9 Branch





(Reporter: hauberg, Assigned: birtles)




(Keywords: perf, Whiteboard: [invalidation] [in-the-wild] [external-report])


(4 files, 1 obsolete file)

User Agent: Mozilla/5.0 (Ubuntu; X11; Linux i686; rv:9.0.1) Gecko/20100101 Firefox/9.0.1
Build ID: 20111221215619

Steps to reproduce:

I have been using Sozi [1] to create slides for my thesis. This gives an SVG file which I then show using Firefox. This works very nicely, but animations are not particularly smooth. You can see a real-world example (slides from my thesis defence) online at

(you change slides by pressing space). On my Linux computer these animations are rather "jaggy".


Actual results:

Animations are not smooth.

Expected results:

The animations should have been nice and smooth (they are in Chromium)
Component: Untriaged → SVG
Product: Firefox → Core
QA Contact: untriaged → general
The svg linked to is using javascript to animate SVG, and not actually using declarative SVG animation, so it would improve more as the JS engine is directly improved, and accelerated with Hardware Acceleration on. From IRC:
<birtles> hmm, looks like that library is using setAttribute("transform", "...")---so probably it's not going to get much of a win from bug 629200 [which has a] patch that makes a big difference when you use the SVG APIs, not the generic DOM setAttribute. If the library was rewritten to use the SVG APIs it might be faster. [As it is] in Chrome when it does animate it's not much different to Aurora on my machine.
Fwiw, Brian's machine specs and the try builds for testing bug 629200 patches follow:
<birtles> I'm on i7-2620M (2 x 2.7Ghz), 8Gb
I tried the Aurora builds and still see "jaggy" animations. Fwiw., my machine is a Lenovo ThinkPad T400 with an Intel Core 2 Duo, P8600 @ 2.40 GHz with 4GB RAM.
I need to do some profiling to see what's going on here.
Assignee: nobody → birtles
Ever confirmed: true

I faced the same performance issue with an animation I made a few months ago.
It is pure SVG animation without any Javascript. Feel free to use it as a test animation :
Keywords: perf
Updating the title since "SVG Animations" is often used to mean "declarative animations", i.e. <animate> and co. while the test case here uses script for animation (RequestAnimationFrame + setAttribute).
Summary: SVG animations are slow → Animations of SVG is slow
This is a patch I've been using to produce a test case. If you apply it to a local copy of the file in comment 0 it will automatically drive the animation between two of the frames backwards and forwards 50 times and then dump some output.

The output is a bit suspicious. It seems reasonably accurate for the backwards and forwards case but when running the whole presentation through (using the "runWholeShow" test) it gives values for fps such as 450fps which is clearly wrong. I suspect either there are overlapping animations whose frames are being added together or some counts are not being cleared. For the backwards and forwards case though it seems reasonable and gives fps rates of about 12fps or 15fps.
I've run this through a profiler but have yet to massage the results into something really useful. From a quick glance though I could see that a lot of time is being spent in mozilla::SVGPathData::ConstructPath.

This particular presentation uses paths to represent the equations, hence there's a lot of small paths.

We're mostly calling ConstructPath from nsSVGPathGeometryFrame::GetBBoxContribution (called by UpdateCoveredRegion). I did some investigation to see if we really need to call ConstructPath so often. This patch applied the number of times GetBBoxContribution is called vs the number of times in a row the same bbox is returned is displayed.

For the presentation I discovered that about 96.63% of the time, although we end up returning the same bbox as last time, we still reconstruct the path.
This is a proof of concept to see how we might cache those bboxes rather than recalculating them.

With this patch applied I'm seeing about a 21.25% perf boost for the test case. That is, after a number of runs I get 12.689fps (1% deviation) without the patch and 15.384fps (1% deviation) with the patch.

If we were to use this approach the perf win would likely be less since this patch doesn't compare styles, doesn't detect changes in geometry etc. I'm not sure yet what the final result would be, but I'd hope over 10%.

There's also the potential of a perf hit for cases where the bbox contribution changes every time it is calculated. I'm not sure what those cases would be yet.
Other strategies to consider:
* Making mozilla::SVGPathData::ConstructPath itself faster. Doesn't seem to be as promising as simply calling it less based on my analysis.

Actually, that's it for now. I really need to massage the profile data before I can make any recommendations. When I thought this was about "SVG Animations" (i.e. declarative animations) I had a number of ideas how we might speed this up, but for script there are less options. In future I think we will be able to hardware accelerate declarative SVG animation and that should prove the best route.
(In reply to Jeremie Patonnier from comment #5)
> Hello, 
> I faced the same performance issue with an animation I made a few months ago.
> It is pure SVG animation without any Javascript. Feel free to use it as a
> test animation :

Hi Jeremie,

That's a great demo! However, I think it's best that this bug just addresses the original test case which uses script rather than declarative animation. Feel free to file other bugs for declarative animation--I have a few ideas about things we can try there.
(In reply to Brian Birtles (:birtles) from comment #11)
> Feel free to file other bugs for declarative animation--I have a few ideas
> about things we can try there.

Done on bug 732108 :)
Thinking a little more about the approach outlined in the proof-of-concept patch, as it stands that approach is likely to increase memory usage significantly. If we end up having all that information stuck in an extra heap-allocated block for every path geometry frame that has had its bbox contribution calculated more than once, we'll chew up a fair bit of memory.

If we were to follow such an approach there needs to be a bit more thought about when we start to cache, when we can clear the cache, and just what needs to be stored. When running the test case I saw a lot of paths whose bbox contribution was calculated 0~2 times combined with many others whose bbox contribution was calculated over 100 times. We might be able to add a threshold for when we start to cache.
Hi Brian,

Interestingly, I see that Søren's presentation, although choppy in both browsers, works faster in Chrome 17 on Linux and is very slow on FF 11.

On the other hand, my test presentation here seems to be extremely smooth and fast on FF and quite choppy/slow on Chrome.
Attachment #705035 - Attachment is obsolete: true
Depends on: 839865, 869611, 875175
Whiteboard: [jwatt:invalidation]
Whiteboard: [jwatt:invalidation] → [jwatt:invalidation] [in-the-wild] [external-report]
Nowadays virtually all of the time seems to be spent under PresShell::Paint due to us continuously invalidating pretty much the entire content area as the transform changes (as shown by nglayout.debug.paint_flashing):
Summary: Animations of SVG is slow → JS animations of the 'transform' attribute in an SVG slide show causes lots of expensive invalidation
Whiteboard: [jwatt:invalidation] [in-the-wild] [external-report] → [invalidation] [in-the-wild] [external-report]
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.