Closed
Bug 901795
Opened 11 years ago
Closed 2 years ago
Change the Preferences code not to leak if you register a weak pref observer on a pref which never changes
Categories
(Core :: Preferences: Backend, defect)
Core
Preferences: Backend
Tracking
()
RESOLVED
WONTFIX
People
(Reporter: justin.lebar+bug, Unassigned)
References
Details
(Whiteboard: [MemShrink:P3][lang=C++])
Just as the observer service leaks if you register a weak observer which never gets fired (bug 901753), the prefs service leaks if you register a weak pref observer which never runs (e.g. because the pref never changes). The solution here may be more complicated than using a WeakSet, but I think the machinery in bug 901746 still makes this fixable.
Reporter | ||
Comment 1•11 years ago
|
||
Wow, the prefs code is not optimal. prefapi.cpp keeps a linked list of pref callbacks. Every time we change a pref, we iterate over the whole thing -- because of the way the API is spec'ed, a pref observer for "foo." gets called whenever "foo.anything" is changed. When we iterate over this big list, we don't remove any weak refs we happen upon. Removing a pref observer is O(n) in the number of observers, which is pretty lame. It seems to me that the right thing to do here is to merge the data structure kept by nsPrefBranch.cpp (a hashset of (nsIObserver, char*)) with the linked list kept by prefapi.cpp. I'm not sure how much this matters, but the scenario I'm afraid of is that we have some short-lived object which registers a weak pref listener on some pref which never changes in practice (that's most or all prefs). This could be particularly bad on B2G, as we'll build up weakrefs in this list over months, potentially, and this will slow down all other pref operations.
Reporter | ||
Comment 2•11 years ago
|
||
It seems like optimally, we'd use a trie or a radix tree to represent the pref observers. I think this would make it efficient to find all observers which watch a given prefix. Again, we should figure out how much this matters, but I'd like us not to get blindsided by a late-breaking B2G bug which tickles this.
Reporter | ||
Updated•11 years ago
|
Whiteboard: [MemShrink]
Reporter | ||
Comment 3•11 years ago
|
||
This isn't a simple bug, but it's a nicely self-contained project which might suit someone who enjoys working with data structures and is somewhat familiar with how our code works.
Whiteboard: [MemShrink] → [MemShrink][mentor=jlebar][lang=C++]
Updated•11 years ago
|
Whiteboard: [MemShrink][mentor=jlebar][lang=C++] → [MemShrink:P3][mentor=jlebar][lang=C++]
Justin what would be a simple test case for this, specifically, how do I track this leak. I'm not very familiar with B2G tooling for these things. Will it work on b2g-desktop or do I need a device? NOTE: No immediate plans to take this bug.
Flags: needinfo?(justin.lebar+bug)
Reporter | ||
Comment 5•11 years ago
|
||
This is mostly a hypothetical thing at this point. I don't know how to cause it, but I'm afraid that there's some path that we'll do 10,000 times in a B2G test in the future that will mess us up here. Your question is a really good one, though. As a prerequisite to this, we should write a memory reporter that counts the number of pref observers. Even better would be to write a memory multi-reporter which reports separately a) Strong pref observers. b) Weak pref observers whose referent is alive. c) Weak pref observers whose referent is dead. We should do this for the observer service, too; that would have made bug 901416 obvious. I'll file bugs for these.
Flags: needinfo?(justin.lebar+bug)
Hi, if it is fit for a complete newbie in the mozilla tree, I can take on this bug.
Reporter | ||
Comment 7•11 years ago
|
||
I guess it depends on how good you are at C++ and figuring out large codebases. :) Maybe give it a try and let us know how it goes? See also the discussion in bug 903285 for tips.
Ok, i'll investigate it and get back to you in the next couple of days.
Comment 9•11 years ago
|
||
Hi Miguel, are you still planning to work on this bug? If not, I would like to give it a try (I'm also a newbe :) ).
Comment 10•11 years ago
|
||
Hi Kamil, go ahead. I've started to look at it a while ago but had to stop and havent been able to pick it up again and it will be a while until having free time again. Cheers
Updated•11 years ago
|
Whiteboard: [MemShrink:P3][mentor=jlebar][lang=C++] → [MemShrink:P3][mentor=jdm][lang=C++]
Comment 11•11 years ago
|
||
Turns out there is a lot I have to learn before fixing this bug, but I can do this if there is no close deadline for it. Nikhil already asked a question about test scenario for this leak - Justin, can you give me some hint? I have latest mozilla-central build and I've found out that I can inspect the number of dead/alive weak references using about:memory page, but so far dead references counter shows 0 :) What I've tried is to change some preferences available in Edit->Preferences menu.
Kamil, jlebar unfortunately doesn't work on the project currently. Josh?
Flags: needinfo?(josh)
Comment 13•11 years ago
|
||
I apologize for taking so long to respond here. I don't know about any kind of automated test for this right now, but inside gBrowserInit.onLoad (http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#739) you could create a pref listener for browser.tabs.remote and add it as a weak reference. I would expect opening up about:memory to show dead references after this (try pressing the GC/CC buttons if that's not true and see if anything changes).
Flags: needinfo?(josh)
Comment 14•11 years ago
|
||
Josh, sorry it took me so long, but I needed to learn more about JS and XPCOM in general. I added the following code: var myObserver = { observe : function observe(a,b,c){ alert("Observing!"); }, QueryInterface : XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]), } gPrefService.addObserver("browser.tabs.remote", myObserver, true); to gBrowserInit.onLoad method. Now, when I open about:memory, I can see that there is one weak dead reference for preference service, and it stays that way even after GC/CC is executed manually - so I suppose this is the desired behavior. I will now start to figure out what prefapi.cpp does :)
Comment 15•11 years ago
|
||
Great; that looks right to me :) Please tag me with "Need more information from" if you have further questions!
Assignee | ||
Updated•10 years ago
|
Mentor: josh
Whiteboard: [MemShrink:P3][mentor=jdm][lang=C++] → [MemShrink:P3][lang=C++]
Updated•3 years ago
|
Mentor: josh
Updated•2 years ago
|
Component: Preferences → Preferences: Backend
Product: Toolkit → Core
Updated•2 years ago
|
Severity: normal → --
Comment 17•2 years ago
|
||
It looks like the callsites mentioned don't exist anymore, and probably haven't existed in a while. We do support weak references in nsPrefBranch
but I don't believe we leak them if we don't use them - this code has been largely rewritten and merged into libpref. I'm going to go ahead and resolve this as wontfix
.
Status: NEW → RESOLVED
Closed: 2 years ago
Flags: needinfo?(kwright)
Resolution: --- → WONTFIX
You need to log in
before you can comment on or make changes to this bug.
Description
•