Closed
Bug 1224845
Opened 10 years ago
Closed 10 years ago
High CPU usage while using WebRTC
Categories
(Core :: WebRTC: Networking, defect, P1)
Tracking
()
RESOLVED
FIXED
mozilla47
| Tracking | Status | |
|---|---|---|
| firefox47 | --- | fixed |
People
(Reporter: marco, Assigned: drno)
References
Details
(Keywords: regression)
Attachments
(8 files, 1 obsolete file)
A call drained my battery in ~30 minutes, Firefox was using ~100% of one of the CPU cores.
| Reporter | ||
Comment 1•10 years ago
|
||
This is pretty bad, even on my new ThinkPad W541.
| Reporter | ||
Comment 2•10 years ago
|
||
| Reporter | ||
Updated•10 years ago
|
Component: Client → Untriaged
Product: Hello (Loop) → Core
| Reporter | ||
Comment 3•10 years ago
|
||
83.9% of the profile is in the poll syscall.
I guess this is either a WebRTC or graphics issue.
Version: unspecified → Trunk
| Reporter | ||
Updated•10 years ago
|
Keywords: regression
| Reporter | ||
Comment 4•10 years ago
|
||
22% is in XUnlockDisplay.
16% is in mozilla::FrameLayerBuilder::PaintItems(nsTArray<mozilla::FrameLayerBuilder::ClippedDisplayItem>.
So I think it's a Graphics bug.
Component: Untriaged → Graphics
| Reporter | ||
Comment 5•10 years ago
|
||
CPU usage was high even when disabling video on both ends.
| Reporter | ||
Comment 6•10 years ago
|
||
Looks like it's not only in Firefox Hello, but also other websites using WebRTC (e.g. https://apprtc.blogspot.com/).
| Reporter | ||
Updated•10 years ago
|
Component: Graphics → WebRTC
| Reporter | ||
Comment 7•10 years ago
|
||
| Reporter | ||
Updated•10 years ago
|
Summary: High CPU usage while using Firefox Hello → High CPU usage while using WebRTC
Comment 9•10 years ago
|
||
FYI
Rank: 15
Component: WebRTC → WebRTC: Networking
Flags: needinfo?(drno)
Priority: -- → P1
| Assignee | ||
Comment 10•10 years ago
|
||
I'm wondering if the amount of IPv6 addresses increases the problem. Because my Ubuntu desktop machine in the Mozilla Mountain View office seems to collect IPv6 addresses like crazy. Marco could you please check if and how many IPv6 addresses your laptop has?
| Reporter | ||
Comment 11•10 years ago
|
||
I have three addresses for the WiFi interface:
2001:450:1d:232:5ec5:d4ff:fedf:985a/64 Scope:Global
2001:450:1d:232:a90f:5e7:398a:2032/64 Scope:Global
fe80::5ec5:d4ff:fedf:985a/64 Scope:Link
| Assignee | ||
Comment 12•10 years ago
|
||
Indeed we have a regression here between 41 and 42 on Linux only. On my Ubuntu desktop machine I get for a WebRTC call in appr.tc:
- 41: ~80% CPU load (IPv4 connection)
- 42: ~140% CPU load (over IPv4 and IPv6 connections)
On Mac I only see a difference of maybe 5-10% in CPU load, but I would assume that is in the area of measurement fault.
Flags: needinfo?(drno)
| Assignee | ||
Comment 13•10 years ago
|
||
Forgot to add that I think the Gecko profiler data doesn't help us much here, because even on Mac the Gecko Profiler shows me that Firefox spends 80-90% of its time in polling the network connections (which makes perfect sense because we receive and send packets at very high rates).
Comment 14•10 years ago
|
||
e10s or not? I think 41 and 42 had e10s on in Nightly, but certainly not in beta or release, so I'm assuming not.
Gecko Profiler only profiles threads that opt-in, and that doesn't include webrtc.org threads/pthreads generally.
System-level profilers or the internal jprof profiler do work. jprof is linux-only but that's what we need here.
add ac_add_options --enable-jprof to .mozconfig, and 'JPROF_FLAGS="JP_DEFER JP_PERIOD=0.002"' to the env vars
Then after starting firefox, do kill -PROF <pid of process>.
Let the test run for a little while (longer the better - a few minutes is more than enough). Then "kill -USR1 <pid>" to stop profiling (you can turn it on and off multiple times - even from JS in non-e10s mode, though I haven't tried that recently).
Flags: needinfo?(drno)
Updated•10 years ago
|
Assignee: nobody → rjesup
| Assignee | ||
Comment 15•10 years ago
|
||
I used 41 and 42 release builds download from our website. So no e10s involved.
Flags: needinfo?(drno)
Comment 16•10 years ago
|
||
I tried 41 & 42 (and the revs before and after the ipv6 landing) on Fedora 22 (with a local ipv4 address used, though I have an IPV6 address it appears). No change in CPU usage worth speaking of. Talky.io calls were ~55-62%.
$ ifconfig
em1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.17 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::1a03:73ff:fec5:2cdc prefixlen 64 scopeid 0x20<link>
ether 18:03:73:c5:2c:dc txqueuelen 1000 (Ethernet)
| Reporter | ||
Comment 17•10 years ago
|
||
I found the regression range using mozregression.
The easiest way to reproduce the issue was disabling e10s (which makes CPU usage clearer to see) and opening https://apprtc.appspot.com/.
Comment 18•10 years ago
|
||
(In reply to Marco Castelluccio [:marco] from comment #17)
> I found the regression range using mozregression.
> The easiest way to reproduce the issue was disabling e10s (which makes CPU
> usage clearer to see) and opening https://apprtc.appspot.com/.
I don't see a CPU difference between 41 and 42, let alone on either side of the regression range. (Maybe it's 55-60% vs 57-63%, maybe - that's way less than anything reported, and in the noise floor). My jprof runs aren't any use if I'm not seeing the effect.
My guess is it has to do either with networking differences between Ubuntu and Fedora, network driver differences (unlikely), or the network environment (in particular IPV6 addresses and LAN setup). Any details on the network setup, OS version, network config and HW would be hugely helpful.
You could try building on either side of the regression (opt builds) with ac_add_options --enable-jprof in .mozconfig. Then cd to objdir/dist/bin, start firefox (using a non-e10s profile) with env vars of JPROF_FLAGS="JP_DEFER JP_PERIOD=0.002". Start a webrtc call. from another shell, use "kill -PROF <pid_of_firefox>". Let it sit for 5 minutes, then "kill -USR1 <pid_of_firefox>". Quite firefox, and do "./jprof firefox jprof.log >/tmp/profile.html".
I realize this does require doing local builds - sorry. Do this once for before the regression, and once after, and attach the html files here.
Flags: needinfo?(mar.castelluccio)
| Reporter | ||
Comment 19•10 years ago
|
||
I'm currently at home for the holidays, where I can't reproduce the issue. I can do that once I'm back in my office, but it's going to take some time.
Maybe Nils can do it earlier than me?
Flags: needinfo?(mar.castelluccio) → needinfo?(drno)
Comment 20•10 years ago
|
||
Nils is away for the holidays as well. Whomever gets home first wins! ;-)
| Assignee | ||
Comment 21•10 years ago
|
||
Looks like canceling poll() in our GTK code is adding massive delays.
Flags: needinfo?(drno)
| Assignee | ||
Comment 22•10 years ago
|
||
After digging around in the profiler output and the code a little bit more it looks to me like:
A) The higher CPU usage is not caused by the way WebRTC/nICEr uses the network sockets
B) It looks to me this is some strange bug caused by the way how necko uses poll(), probably in combination with some OS specific (Ubuntu?) or other environment infused problem.
Randel what are your thoughts on the profiler output?
Flags: needinfo?(rjesup)
Comment 23•10 years ago
|
||
The DoPollIteration numbers implies to me TONS of poll wakeups. That's 4.6% directly in that routine (walking the socket arrays), and 60% spent in that routine or others it calls (~19% in poll(), ~22% in nsSSLIOLayerPoll(PRFileDesc*, short, short*))
On Nightly Linux64 Fedora 22 debug, I see 2.1% total in DoPollIteration() in an apprtc call to another machine on the lan. I do have (1) IPV6 address assigned, in addition to a 192.168.x.x
Flags: needinfo?(rjesup)
| Assignee | ||
Comment 24•10 years ago
|
||
Another profile from the same machine, same call via appr.tc, approximately same call length of about 5 mins. Only difference is that at the time of the first profile the machine had 4 IPv6 addresses. For this run the machine had only 2 IPv6 addresses.
Comment 25•10 years ago
|
||
The difference is basically in the noise. 57% DoPollIteration vs 60%
If you can try with IPV6 support disabled (or the interfaces disable/blocked) that would be good.
| Assignee | ||
Comment 26•10 years ago
|
||
Profile of the same call but from Fedora 21 with only one IPv6 address.
That still looks like a lot of time being spend in DoPollIteration().
| Assignee | ||
Comment 27•10 years ago
|
||
This is the same call as before, but with IPv6 disabled via sysctl on the same Fedora 21 machine.
Clearly we have networking issue with IPv6.
| Assignee | ||
Comment 28•10 years ago
|
||
NSPR log file taken with nsSocketTransport:5 on the machine with only a single IPv4 address active.
| Assignee | ||
Comment 29•10 years ago
|
||
NSPR log taken with nsSocketTransport:5 on the same machine, this time the single Ethernet interface on the machine had IPv4 and IPv6 addresses available. The WebRTC called used only the v4 addresses as the other side did not provide v6 addresses.
| Assignee | ||
Comment 30•10 years ago
|
||
The two nsSocketTransport log files look quite a bit different to me.
But I still can't tell what is going wrong here. Is simply that with IPv6 17 instead of 11 are polled?
The other difference seems to be the number of socket just with the PR_POLL_READ flag is a lot higher. So it looks almost as if most of our IPv4 socket have PR_POLL_READ & PR_POLL_EXCEPT set, but the IPv6 socket have only PR_POLL_READ. But I have no idea why that would cause so much more time getting spend in poll calls.
Any advice on how to debug this further?
Flags: needinfo?(rjesup)
Flags: needinfo?(mcmanus)
| Assignee | ||
Comment 31•10 years ago
|
||
Might be interesting to note that WebRTC's nICEr uses/sets PR_POLL_READ and PR_POLL_WRITE, but PR_POLL_EXCEPT doesn't show up at all in media/metransport/*. So I guess PR_POLL_EXCEPT gets set on the IPv4 sockets by some network code, but not on the IPv6 sockets. Could this result in the network code missing some errors and thus getting into this busy mode?
Comment 32•10 years ago
|
||
poll() exceptions are often unmaskable (they will be returned whether or not you ask for them at the OS level).. so i could imagine some code in necko adding the POLL_EXCEPT because it had an explicit error path to deal with it, but the media transport code not being aware to look for it (but still getting the wakeup when it just polled for read, because it is unmaskable).
nsSocketTransport2 never (afaik anyhow) sets READ or WRITE without also setting except at the pollflags level. but I think you're using a different transport, right? (i.e. using sockettransportservice, but not sockettransport..)
Flags: needinfo?(mcmanus)
| Assignee | ||
Comment 33•10 years ago
|
||
Once I'm back in the office I can try to add POLL_EXCEPT if we set READ or WRITE and see what happens. Although that still leaves the questions open how it can happen that in the IPv4 scenario something apparently sets POLL_EXCEPT, but does not seem to set it for IPv6.
The bigger more important question: do you think trying to investigate the POLL_EXCEPT differences makes sense, or what else would you suggest to find out why with IPv6 sockets poll() seems to return so much more often?
Flags: needinfo?(mcmanus)
Comment 34•10 years ago
|
||
It'd be easy to find where POLL_EXCEPT is set for IPV4 using rr
Flags: needinfo?(rjesup)
| Assignee | ||
Comment 35•10 years ago
|
||
So I added PR_POLL_EXCEPT to nICEr's READ and WRITE flags. As expected this results in all of the pollflags in the NSPR log to be mostly 5's and very few 7's. But CPU usage is still as high as before.
| Assignee | ||
Comment 36•10 years ago
|
||
Added a line to the nICEr code which gets called if PR_POLL_EXCEPT gets set. Result: never enters that line in the debugger.
So I guess the whole PR_POLL_EXCEPT business is a red herring.
Any other ideas how to find out what is going wrong here?
Comment 37•10 years ago
|
||
We could run it under rr in v4 and v6 modes, and see if anything looks odd. THat does warp a lot of things
| Assignee | ||
Comment 38•10 years ago
|
||
I did get rr working after some fighting. But by the time my Ubuntu machine had collected several temporary IPv6 addresses again. I'll try to get a new log tomorrow with only a single or two IPv6 addresses, as I know that the amount of IPv6 addresses does not affect the problem.
What I can tell from playing a little bit around with the rr recording is that poll() basically returns super quickly (you can basically extract information already from the NSPR logs) claiming 40 sockets have updates, but when the NSPR poll loop iterates through the sockets it does not find a single socket in the 'ready' state.
I started working on modifying one of our unit tests to see if I can get it to reproduce the problem. Unfortunately it turns out that our nICEr socket tests don't use poll() at all. And our TransportService tests use local pipes. So it requires some hacking to get there...
| Assignee | ||
Comment 39•10 years ago
|
||
These are the "returned after" numbers from the two NSPR logs:
IPv4 IPv6
# ms # ms
1458 0 199579 0
348 1 2974 1
334 2 5 2
293 3 5 3
227 4 5 4
250 5 3 5
105 6 3 6
58 7 3 7
48 8 3 8
39 9 2 9
46 10 1 10
25 11
25 12 3 12
30 13 4 13
35 14 3 14
32 15
49 16
33 17 2 17
9 18 1 18
3 19
1 20
... ...
1 9575 1 3892
Another evidence that the presence of IPv6 sockets results in lot less sleeping.
Updated•10 years ago
|
Flags: needinfo?(mcmanus)
| Assignee | ||
Comment 40•10 years ago
|
||
Apparently trying to connect to a IPv4 address from a IPv6 TCP socket results in a POLLHUP being generated. And our OnSocketReady() only pays attention to PR_POLL_READ and PR_POLL_WRITE, as these are the only two flags we set :-(
| Assignee | ||
Comment 41•10 years ago
|
||
I'll test a patch I have created once I'm back in the office.
| Reporter | ||
Comment 42•10 years ago
|
||
I can test it if you attach the patch here (or even better send it to try).
Comment 43•10 years ago
|
||
(In reply to Nils Ohlmeier [:drno] from comment #40)
> Apparently trying to connect to a IPv4 address from a IPv6 TCP socket
> results in a POLLHUP being generated. And our OnSocketReady() only pays
> attention to PR_POLL_READ and PR_POLL_WRITE, as these are the only two flags
> we set :-(
this is a great find.. and this is the kind of thing I was thinking of when I said that some errors are unmaskable at the OS level...
| Assignee | ||
Comment 44•10 years ago
|
||
As mozreview is down right now here is the patch which fixes the problem. Is has two parts in it:
1) close sockets once NSPR tells us about any error on a socket (to avoid the busy loop we were trapped in)
2) don't try to connect a v6 socket to a v4 TURN TCP server (which caused the problem in the first problem)
Comment 45•10 years ago
|
||
Thanks for digging into this, Nils. At this point, it makes sense for you to (officially) take this over.
Assignee: rjesup → drno
| Assignee | ||
Comment 46•10 years ago
|
||
Review commit: https://reviewboard.mozilla.org/r/32917/diff/#index_header
See other reviews: https://reviewboard.mozilla.org/r/32917/
Attachment #8713946 -
Flags: review?(rjesup)
| Assignee | ||
Comment 47•10 years ago
|
||
Comment on attachment 8713946 [details]
MozReview Request: Bug 1224845: close sockets on errors and don't connect to IPv4 TURN TCP from IPv6 sockets. r=jesup
Review request updated; see interdiff: https://reviewboard.mozilla.org/r/32917/diff/1-2/
| Assignee | ||
Comment 48•10 years ago
|
||
Comment on attachment 8713946 [details]
MozReview Request: Bug 1224845: close sockets on errors and don't connect to IPv4 TURN TCP from IPv6 sockets. r=jesup
Review request updated; see interdiff: https://reviewboard.mozilla.org/r/32917/diff/2-3/
| Assignee | ||
Comment 49•10 years ago
|
||
Comment on attachment 8713946 [details]
MozReview Request: Bug 1224845: close sockets on errors and don't connect to IPv4 TURN TCP from IPv6 sockets. r=jesup
Review request updated; see interdiff: https://reviewboard.mozilla.org/r/32917/diff/3-4/
| Assignee | ||
Comment 50•10 years ago
|
||
Marco in case you want to double check my patch a try run is finally on its way: https://treeherder.mozilla.org/#/jobs?repo=try&revision=1d38c10b6b0b
Updated•10 years ago
|
Attachment #8713946 -
Flags: review?(rjesup) → review+
Comment 51•10 years ago
|
||
Comment on attachment 8713946 [details]
MozReview Request: Bug 1224845: close sockets on errors and don't connect to IPv4 TURN TCP from IPv6 sockets. r=jesup
https://reviewboard.mozilla.org/r/32917/#review29735
| Assignee | ||
Updated•10 years ago
|
Attachment #8713385 -
Attachment is obsolete: true
| Assignee | ||
Comment 52•10 years ago
|
||
Looks like the patch is causing a almost perma orange on Linux debug builds. Need to investigate...
Flags: needinfo?(drno)
| Reporter | ||
Comment 53•10 years ago
|
||
I've tried the try build, it doesn't really make a difference for me.
| Assignee | ||
Comment 54•10 years ago
|
||
(In reply to Marco Castelluccio [:marco] from comment #53)
> I've tried the try build, it doesn't really make a difference for me.
Quick question Marco: are you running things in e10s mode?
I just realized that tested everything only without e10s. Quite possible that it is still broken with e10s turned on.
| Reporter | ||
Comment 55•10 years ago
|
||
(In reply to Nils Ohlmeier [:drno] from comment #54)
> Quick question Marco: are you running things in e10s mode?
> I just realized that tested everything only without e10s. Quite possible
> that it is still broken with e10s turned on.
e10s was enabled, but I was using Firefox Hello (that only works in a non-e10s window).
| Assignee | ||
Comment 56•10 years ago
|
||
I tried profiling a plain e10s call and don't see anything strange. For a Firefox Hello call CPU usage is higher then for a plain WebRTC A/V call. But the profiling of such a call just points to the screen sharing taking a lot of CPU.
I also double checked that for me the patch here drops the CPU usage in a Firefox Hello call from ~220% to ~140% (FYI a plain WebRTC A/V call is ~90% CPU).
If the problem is still not better with the patch applied I think we would now need a profile from your machine Marco, to get an idea where it's spending its CPU time.
| Reporter | ||
Comment 57•10 years ago
|
||
I attached a profile, I'll collect another one with your patch applied.
I'll test again with a plain A/V call with/without your patch.
| Assignee | ||
Comment 58•10 years ago
|
||
Comment on attachment 8713946 [details]
MozReview Request: Bug 1224845: close sockets on errors and don't connect to IPv4 TURN TCP from IPv6 sockets. r=jesup
Review request updated; see interdiff: https://reviewboard.mozilla.org/r/32917/diff/4-5/
| Assignee | ||
Comment 59•10 years ago
|
||
Looks like the oranges were actually not caused by my patch. Lets see how a rebased try run will perform.
| Assignee | ||
Comment 60•10 years ago
|
||
Try run looks good now. Let's land this as I'm 100% certain that this fixes real problems.
Marco if you are still experiencing problem with/after this fix, we can look at that in a new bug.
Flags: needinfo?(drno)
Keywords: checkin-needed
| Reporter | ||
Comment 61•10 years ago
|
||
(In reply to Nils Ohlmeier [:drno] from comment #60)
> Try run looks good now. Let's land this as I'm 100% certain that this fixes
> real problems.
>
> Marco if you are still experiencing problem with/after this fix, we can look
> at that in a new bug.
I've tested again. CPU usage is still quite high, but the patch fixes the original regression.
Most of the time is still spent in poll: https://cleopatra.io/#report=f71a7c620f0cbd72ff6fabc15352bb1743d99aff
Comment 62•10 years ago
|
||
Keywords: checkin-needed
Comment 63•10 years ago
|
||
| bugherder | ||
Status: NEW → RESOLVED
Closed: 10 years ago
status-firefox47:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla47
| Reporter | ||
Comment 64•10 years ago
|
||
Should I file a new bug for the profile in comment 61 or is there nothing we can do?
Flags: needinfo?(drno)
| Assignee | ||
Comment 65•10 years ago
|
||
Macro I filled bug 1245590 as a follow up to investigate if we can reduce the overhead from screen share. I think that is an appropriate bug to add your information to.
Flags: needinfo?(drno)
You need to log in
before you can comment on or make changes to this bug.
Description
•