Closed Bug 584500 Opened 11 years ago Closed 8 years ago

SVG SMIL animations consume large amounts of CPU time even when ended.

Categories

(Core :: SVG, defect)

x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: griffin_m82, Unassigned)

References

Details

(Keywords: perf, Whiteboard: [external-report])

Attachments

(2 files)

User-Agent:       Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8
Build Identifier: Mozilla/5.0 (X11; Linux x86_64; rv:2.0b3pre) Gecko/20100731 Ubuntu/10.04 (lucid) MozillaDeveloperPreview/4.0b3pre

SVG SMIL animations consume unusual amounts of CPU even if the animations are stopped. The point is not the absolute level as compared to other browsers (that is a performance issue), the point is that a stopped animation should not be consuming a noticable amount of CPU time. The following shows some rough measurements made using the accompanying test case file.

Firefox 4
When running:	When Stopped:
Firefox - 36%	16%
Xorg - 33%	19%

By comparison, Opera and Chromium consume virtually no CPU when the animation is stopped (this is as should be expected). The rough measurements for those are given below:

Opera
When running:	When Stopped:
Opera - 30%	negligible
Xorg - 12%	negligible

Chromium
When running:	When Stopped:
Chrome - 18%	negligible
Xorg - 6%	negligible

The area of application is when multiple animations are present on a page, but only one or a few are running at any one time. The inactive animations should not be adding to the (already relatively high) CPU consumption.

A file with "animatebugs.svg" contains 6 different simple animations using different techniques. If you click on the green areas, you will stop the animation. If you click on the red areas, you will restart the animations. If you want to run a comparative test against a web browser using Webkit, take note that Webkit has its own somewhat different bugs in this area (and an appropriate bug has been filed with them). Opera seems to work correctly in all respects for these tests.

The functionality exposed in these tests appears to be correct in Firefox. The question raised here is the CPU usage when stopped. Better performance when running would be nice too, but that is a separate issue. I did not find any existing bugs which appear to be directly related to this issue. 


Reproducible: Always

Steps to Reproduce:
1. Load the provided SVG test file.
2. Note the CPU usage (e.g. using "top").
3. Stop each animation.
4. Note the CPU usage again.
Actual Results:  
When running:	When Stopped:
Firefox - 36%	16%
Xorg - 33%	19%


Expected Results:  
CPU usage when stopped should be close to zero. 

Here is the test case.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="750"
   height="750">


<text x="50" y="25" >Click on a green rectangle to stop an animation. Click on red rectangle to restart it.</text>

<!-- ##################################################################################### -->
<!-- animate -->

<!-- Show/hide. -->
<g transform="translate(50,50)">
	<!-- this provides the background. -->
	<rect onclick="endtest('1');" x="0" y="0" width="90" height="90" fill="green" stroke="black" stroke-width="5" rx="10" ry="10" />

	<g onclick="begintest('1');">
		<rect x="20" y="20" width="50" height="50" fill="red" stroke="black" stroke-width="5" rx="10" ry="10" >
			<animate id="test1" attributeType="CSS" attributeName="display" from="block" to="none" dur="1.0s" 
							repeatCount="indefinite" />
	</rect>
	</g>
	<text x="0" y="110" >animate - display</text>
</g>


<!-- Opacity. -->
<g transform="translate(250,50)">
	<!-- this provides the background. -->
	<rect onclick="endtest('2');" x="0" y="0" width="90" height="90" fill="green" stroke="black" stroke-width="5" rx="10" ry="10" />

	<g onclick="begintest('2');">
		<rect x="20" y="20" width="50" height="50" fill="red" stroke="black" stroke-width="5" rx="10" ry="10" >
			<animate id="test2" attributeType="CSS" attributeName="opacity" from="0.0" to="1.0" dur="1.0s" 
							repeatCount="indefinite" />
	</rect>
	</g>
	<text x="0" y="110" >animate - opacity</text>
</g>


<!-- ##################################################################################### -->
<!-- animateTransform -->


<!-- Rotate. -->
<g transform="translate(50,250)">
	<!-- this provides the background. -->
	<rect onclick="endtest('3');" x="0" y="0" width="90" height="90" fill="green" stroke="black" stroke-width="5" rx="10" ry="10" />

	<g onclick="begintest('3');" transform="translate(45,45)">
		<rect x="-25" y="-25" width="50" height="50" fill="red" stroke="black" stroke-width="5" rx="10" ry="10" >

			<animateTransform id="test3" attributeName="transform" attributeType="XML"
					type="rotate" from="0" to="360" dur="5s" repeatCount="indefinite" 
					additive="sum" fill="freeze" accumulate = "sum"/>
	</rect>
	</g>
	<text x="0" y="110" >animateTransform</text>
	<text x="0" y="125" >- rotate</text>
</g>



<!-- Scale. -->
<g transform="translate(250,250)">
	<!-- this provides the background. -->
	<rect onclick="endtest('4');" x="0" y="0" width="90" height="90" fill="green" stroke="black" stroke-width="5" rx="10" ry="10" />

	<g onclick="begintest('4');" transform="translate(45,45)">
		<rect x="-25" y="-25" width="50" height="50" fill="red" stroke="black" stroke-width="5" rx="10" ry="10" >

		<animateTransform id="test4" attributeName="transform" attributeType="XML"
				type="scale" from="0" to="1" dur="1s" repeatCount="indefinite"
				additive="replace" fill="freeze"/>
	</rect>
	</g>
	<text x="0" y="110" >animateTransform</text>
	<text x="0" y="125" >- scale</text>
</g>



<!-- Translate. -->
<g transform="translate(450,250)">
	<!-- this provides the background. -->
	<rect onclick="endtest('5');"  x="0" y="0" width="90" height="90" fill="green" stroke="black" stroke-width="5" rx="10" ry="10" />

	<g onclick="begintest('5');" transform="translate(45,45)">
		<rect x="-25" y="-25" width="50" height="50" fill="red" stroke="black" stroke-width="5" rx="10" ry="10" >

		<animateTransform id="test5" attributeName="transform" attributeType="XML"
				type="translate" from="-25" to="25" dur="5s" repeatCount="indefinite"
				additive="sum" fill="freeze"/>
	</rect>
	</g>
	<text x="0" y="110" >animateTransform</text>
	<text x="0" y="125" >- translate</text>
</g>


<!-- ##################################################################################### -->
<!-- animateMotion -->

<!-- Motion. -->
<g transform="translate(50,450)">
	<!-- this provides the background. -->
	<rect onclick="endtest('6');"  x="0" y="0" width="90" height="90" fill="green" stroke="black" stroke-width="5" rx="10" ry="10" />

	<g onclick="begintest('6');" transform="translate(45,45)">
		<rect x="-25" y="-25" width="50" height="50" fill="red" stroke="black" stroke-width="5" rx="10" ry="10" >

		<animateMotion id="test6" path="M -20 0 L 20 0" dur="5s" repeatCount="indefinite" fill="freeze"/>

	</rect>
	</g>
	<text x="0" y="110" >animateMotion</text>
</g>



	<script type="text/javascript">
  <![CDATA[

	// Start the selected animation. 
	function begintest(testnumber) {
		var cellref = document.getElementById("test" + testnumber);
		cellref.beginElement();
	}

	// Stop the selected animation. 
	function endtest(testnumber) {
		var cellref = document.getElementById("test" + testnumber);
		cellref.endElement();
	}

	]]>
	</script>

</svg>
Looks OK on windows i get about 3% cpu utilization when running, 1% to 0% when stopped. I'll check on Linux when I reboot next. Mozilla/5.0 (Windows; Windows NT 6.1; WOW64; rv:2.0b3pre) Gecko/20100804 Minefield/4.0b3pre
I can confirm the CPU usage on Linux -- I get ~25% CPU usage for Firefox & Xorg with animations running, and ~10% after I've clicked all the green squares.

This sounds like a sort-of duplicate of bug 562815.  Note that "endElement()" doesn't exactly "stop" the animations -- it just ends their current interval.  /me updates the bug summary. (The semantics there important, because animations with fill="freeze" can still have effects after their current-interval has ended, and hence still need to be sampled in some cases.  In contrast, if you call pauseAnimations() on the document, that does actually "stop" the animation & will stop all CPU usage.)
Summary: SVG SMIL animations consume large amounts of CPU time even when stopped. → SVG SMIL animations consume large amounts of CPU time even when ended.
I'm not duping from bug 562815 for now, since that bug's specifically about frozen animations, and this doesn't have fill="freeze" on any of its CSS animations.  (opacity, display)

It'd be interesting to see whether this bug is still reproducible in a testcase that *only* uses <animateTransform> elements. (which, unlike CSS properties, should all benefit from the optimization in bug 533291)
Status: UNCONFIRMED → NEW
Ever confirmed: true
I just tested this on MS Windows XP with a freshly installed copy of Firefox 4 beta, and got the following:

Running: 50% CPU
Stopped: 1-2% CPU

This is running on a different computer than the one used for the Linux test, so the numbers are not comparable between the two. 

As for reproducing it with a test that only uses animateTransform, the results are:

With *only* animate:

Running: Firefox 20%, Xorg 20%
Stopped: Firefox 17%, Xorg 17%


With *only* animateTransform:

Running: Firefox 50%, Xorg 30%
Stopped: Firefox 3%, Xorg 2%


With *only* animateMotion:

Running: Firefox 10%, Xorg 10%
Stopped: Firefox 1%, Xorg 0.3%


With animateTransform *and* animateMotion:

Running: Firefox 30%, Xorg 25%
Stopped: Firefox 2%, Xorg 0.3%


The problem appears to be in "animate" on Linux. The above tests were done using the same test file as before, but with the different tests cut out as necessary.

To answer the question as to why to use "endElement()" rather than "pauseAnimations()" - my understanding of pauseAnimations is that it stops all animations in the document. The objective here is to start and stop them selectively to reflect the state of different data as it changes in an AJAX application. The web browser regularly polls the server for data, and the updated data is presented to the user in the form of animations (e.g. flashing alarm lights, rotating turbines, etc.).

At this point it looks like the issue is with animate on Linux.
(In reply to comment #5)
> To answer the question as to why to use "endElement()" rather than
> "pauseAnimations()" - my understanding of pauseAnimations is that it stops all
> animations in the document.

Correct -- sorry, I wasn't actually questioning your use of endElement() -- I was merely pointing out that it doesn't technically "stop" animations -- which is why there's still some (probably inefficient) computation going on in the background.  I agree that it's an appropriate API call to make for many use cases.

> At this point it looks like the issue is with animate on Linux.

Ok -- if it's specific to <animate>, then that means this is probably the same root cause as bug 562815.
Blocks: 562815
Yes, it is possible it may have the same root cause as 562815. That example is using animate with opacity (although in a different way), and as the elements accumulate the CPU time for inactive opacity transforms will accumulate rapidly to 100% CPU usage. 

As to whether animations are "stopped" or not is a matter of semantics. From the user's point of view, there are not supposed to be any changes going on so there shouldn't be any CPU usage required. It might look differently from inside the implementation, but the reason for calling "endElement()" is to "stop" whatever the animation was doing. In the case of the "catch the mouse" demo, the animations had terminated because they were "done". In my case, I need to turn them on or off at arbitrary times in a simple manner. 

The fact that this problem doesn't seem to appear on the MS Windows version suggests that the problem isn't fundamental to the design of Firefox.

I suspect that one of the most common uses for "animate" will be opacity animations to give fade-in / fade-out effects. It might even be worthwhile to provide a special case to optimize that. This last bit of course is just a suggestion which is not part of this bug report.
I have added a new test case using "animate" only. "Test case showing animations using animate only". This also animates several properties that were not attempted in the first test case, but all use "animate" which at this point appears to be the problematic feature.

The stroke-width case unintentionally illustrates another bug involving the use of "0" as a starting value, but I believe this bug is already covered under 556441 and so can be ignored here.
Keywords: perf
Seems fixed now. Presumably due at least in part to bug 758505
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → WORKSFORME
Whiteboard: [external-report]
You need to log in before you can comment on or make changes to this bug.