Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upRemoved mutex from Trusted, used weak references #12899
Conversation
… to gc dead references.
highfive
commented
Aug 17, 2016
|
Heads up! This PR modifies the following files:
|
highfive
commented
Aug 17, 2016
|
@jdm is on PTO I believe. r? @Manishearth |
| fn remove_nulls<K: Eq + Hash + Clone, V> (table: &mut HashMap<K, Weak<V>>) { | ||
| let to_remove: Vec<K> = | ||
| table.iter() | ||
| .filter(|&(_, value)| Weak::upgrade(value).is_none()) |
This comment has been minimized.
This comment has been minimized.
Manishearth
Aug 17, 2016
Member
Ick. It would be nice if there was an API for this, as it stands we needlessly bump and unbump the refcount.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Manishearth
Aug 17, 2016
Member
Yep, that's why that API doesn't exist, the synchronization semantics need to be decided by the caller.
As far as racing here goes, that's okay -- a few extra references hanging around as live when they aren't is nbd. It will get caught in the next pass.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nox
Aug 17, 2016
Member
I don't understand why we can't use the entry API here, instead of collecting in an intermediate Vec.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Aug 17, 2016
Author
Member
Yes, it would be nice if there was an if_upgradeable that didn't actually do the upgrade. It's racy, but in this case the race is benign, as it just results in gc being delayed.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Aug 17, 2016
Author
Member
@nox: the intermediate result is needed because we can't do the remove in the middle of iterating over the hash map.
|
lgtm, much nicer code now @Ms2ger sanity-check? |
| refcount.clone() | ||
| } | ||
| Occupied(mut entry) => match entry.get().upgrade() { | ||
| Some(refcount) => refcount.clone(), |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Have you measured the perf impact? |
|
@Ms2ger So far I've not seen observable differences on just timing the executable. I'll run gperf and see if it reports anything. |
|
Rather annoyingly, running with the google perf tools causes panics, probably due to timing changes:
Valgrind produces an error:
This is making profiling difficult. |
|
OK, I learned how to use
We're seeing mutex locking going down from 1.18% of cpu to 1.10%. Not exactly a huge drop, but a drop. This is from `perf record ./target/debug/servo -x http://google.com/'. It is doing a bit more memcpy, probably due to trusted objects being GCd later, so the hash table ends up being a bit larger. |
|
Please do rewrite the big documentation comment at the top of the file; I have no clue what's going on here. |
|
Will do. |
|
Documentation rewritten. |
| LIVE_REFERENCES.with(|ref r| { | ||
| let r = r.borrow(); | ||
| let live_references = r.as_ref().unwrap(); | ||
| let table = live_references.table.borrow(); | ||
| let mut table = live_references.table.borrow_mut(); | ||
| remove_nulls(&mut table); |
This comment has been minimized.
This comment has been minimized.
KiChjang
Aug 18, 2016
Member
If I'm reading this correctly, does it mean that the JS GC will call into this code and clean up the RCs on the LiveDOMReferences hash table? And this new process would make the dance between dropping -> sending cleanup message to the script thread -> doing the actual cleanup unnecessary?
This comment has been minimized.
This comment has been minimized.
asajeffrey
Aug 18, 2016
Author
Member
That's the idea, it's replacing the GC message to the owner thread by a use of weak references. There is a slight extra cost, since we only reclaim space in the hash table when GC happens, rather than when the pointer is dropped. (This is a case where something like Java's WeakHashMap would be useful.) But that cost is made up for by saving on messaging.
This comment has been minimized.
This comment has been minimized.
nox
Aug 18, 2016
Member
There is already precedent for such an idiom in Servo itself with the JSTraceable impl of WeakRangeVec in range.rs.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Aug 19, 2016
Author
Member
Hmm, goes and looks... there's a WeakRef implementation in weakref.rs, including an implementation of retain_alive. It's slightly different I think, because Trusted can be sent to other threads, so doesn't have access to the reflector. Also, I can't see an impl of JSTraceable for WeakRefVec, is the expectation that any use of WeakRefVec will impl JSTraceable by hand? WeakRangeVec does.
This comment has been minimized.
This comment has been minimized.
nox
Aug 19, 2016
Member
I didn't say we could use it for Trusted, I was just saying we have a precedent for cleaning stuff up on GC trace.
As for your question, WeakRefVec doesn't implement JSTraceable itself because cleaning up needs mutable access to it.
This comment has been minimized.
This comment has been minimized.
asajeffrey
Aug 19, 2016
Author
Member
Oh that's interesting, JSTraceable only provides immutable access to the object. Does mean you're limited in terms of which tracing algorithms you use, e.g. no pointer reversal.
|
Superseded by #13106. |
asajeffrey commentedAug 17, 2016
•
edited by larsbergstrom
This PR aims to improve performance by:
TrustedDOM object.Weakrefcounts../mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is