Closed Bug 1370674 Opened 7 years ago Closed 7 years ago

ServiceWorkerManager does unnecessary hashtable lookups

Categories

(Core :: DOM: Service Workers, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla56
Tracking Status
firefox56 --- fixed

People

(Reporter: MatsPalmgren_bugz, Assigned: MatsPalmgren_bugz)

References

(Blocks 1 open bug)

Details

(Keywords: perf)

Attachments

(2 files, 3 obsolete files)

No description provided.
Component: DOM: Workers → DOM: Service Workers
Hmm, now that I look at nsBaseHashtable::GetOrInsert() it seems like it's actually doing two lookups anyway... I filed bug 1371061.
BTW, just to clarify the patch a bit: I'm intentionally using "nsCOMPtr<nsITimer>" without a & to hold a strong ref on the stack during the call to Cancel() since it's what the existing code does.
Comment on attachment 8875463 [details] [diff] [review] Use mUpdateTimers.LookupRemoveIf() to avoid a second hashtable lookup for Remove(). Use mUpdateTimers.GetOrInsert() to avoid a second hashtable lookup for Put() Hmm, since the new code here depends on Cancel() not touching the hashtable we might as well use nsCOMPtr<nsITimer>& ...
Attachment #8875463 - Flags: review?(nfroyd)
I guess we can avoid the Remove calls I introduce here if we add a EntryPtr::Remove or some such (and use LookupForAdd instead of GetOrInsert), but these are failure cases that should be very rare. So it doesn't seem worth it.
Attachment #8876250 - Flags: review?(nfroyd)
Attachment #8875463 - Attachment is obsolete: true
This actually introduces a false positive assertion in debug builds. I'll explain and fix that in the next part...
Attachment #8876255 - Flags: review?(nfroyd)
In RemoveAll() we iterate mRegistrationInfos - this opens a PLDHashTable ReadOp for the duration of the iterator. Inside that iteration we call ForceUnregister, which calls Unregister, which calls GetOrCreateJobQueue, which does a hashtable lookup on mRegistrationInfos. Before part 2, this was a Get() which always finds an existing entry, so the Put() was not executed. A Get() counts as a ReadOp, so all is well. However, LookupForAdd calls PutEntry internally, which counts as a WriteOp, because it *might* do a write. It never does that on this path, but PLDHashTable::Add does an *unconditional* AutoWriteOp whether or not an actual write occurs or not, so it asserts: http://searchfox.org/mozilla-central/rev/a798ee4fc323f9387b7576dbed177859d29d09b7/xpcom/ds/PLDHashTable.cpp#541 So, this patch changes ForceUnregister to do the essential part of GetOrCreateJobQueue upfront, without accessing mRegistrationInfos at all. This avoids the false positive assertion. It also saves a hashtable lookup and unnecessary string copying (all of which occurs inside the nested loops of RemoveAll), so this should also be an additional performance win.
Attachment #8876259 - Flags: review?(nfroyd)
Comment on attachment 8876259 [details] [diff] [review] part 3 - Refactor Unregister/ForceUnregister to avoid unnecessary hashtable lookups and string copying. Review of attachment 8876259 [details] [diff] [review]: ----------------------------------------------------------------- This patch is a little more complex than mere hashtable operation adjustment, and I don't think I'm the right reviewer for it.
Attachment #8876259 - Flags: review?(nfroyd) → review?(bkelly)
Comment on attachment 8876259 [details] [diff] [review] part 3 - Refactor Unregister/ForceUnregister to avoid unnecessary hashtable lookups and string copying. Review of attachment 8876259 [details] [diff] [review]: ----------------------------------------------------------------- ::: dom/workers/ServiceWorkerManager.cpp @@ +3684,5 @@ > + // Ensure we pass a non-null queue to avoid calling GetOrCreateJobQueue > + // in UnregisterInternal which would do mRegistrationInfos.LookupForAdd > + // which will cause a false positive assertion since we're iterating it. > + queue = aRegistrationData->mJobQueues.LookupForAdd(aRegistration->mScope).OrInsert( > + []() { return new ServiceWorkerJobQueue(); }); I don't think this right. Running the unregister from an anonymous job queue means any further jobs that might start for this scope after this won't wait for the unregister to complete.
Attachment #8876259 - Flags: review?(bkelly) → review-
Attachment #8876250 - Flags: review?(nfroyd) → review+
Comment on attachment 8876255 [details] [diff] [review] part 2 - Optimize hashtable lookups on mRegistrationInfos, mInfos and mJobQueues Review of attachment 8876255 [details] [diff] [review]: ----------------------------------------------------------------- Since this patch interferes with part 3, I'll let you and bkelly talk through how best to deal with this.
Attachment #8876255 - Flags: review?(nfroyd)
OK, I'll leave the troublesome Get+Put as is and skip part 3.
Attachment #8876255 - Attachment is obsolete: true
Attachment #8876259 - Attachment is obsolete: true
Attachment #8876763 - Flags: review?(nfroyd)
(Filed bug 1372333 on adding a EntryPtr::Remove() method, automatic or not)
Blocks: 1372333
Comment on attachment 8876763 [details] [diff] [review] Optimize hashtable lookups on mRegistrationInfos, mInfos and mJobQueues Review of attachment 8876763 [details] [diff] [review]: ----------------------------------------------------------------- Thanks.
Attachment #8876763 - Flags: review?(nfroyd) → review+
Pushed by mpalmgren@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/9b25910374bd part 1 - Use mUpdateTimers.LookupRemoveIf() to avoid a second hashtable lookup for Remove(). Use mUpdateTimers.GetOrInsert() to avoid a second hashtable lookup for Put(). r=froydnj https://hg.mozilla.org/integration/mozilla-inbound/rev/2882dfa38314 part 2 - Optimize hashtable lookups on mRegistrationInfos, mInfos and mJobQueues. r=froydnj
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: