Closed
Bug 299689
Opened 20 years ago
Closed 19 years ago
Getting lots of elements by ID can be slow
Categories
(Core :: DOM: Core & HTML, defect)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
People
(Reporter: bzbarsky, Assigned: bzbarsky)
References
Details
(Keywords: perf)
Attachments
(1 file, 2 obsolete files)
3.47 KB,
patch
|
Details | Diff | Splinter Review |
The testcase is at the URL of bug 297959, the getElementById test. That test
gets each of the table cells by id, which makes the whole thing O(N^2) in number
of cells, since we have to keep walking over parts of the DOM that we've walked
over before.
Ian's suggestion was that after we've had some number of misses of the
getElementById hashtable we should just assume more misses will come, walk over
the whole DOM and prefill the hashtable. In fact, I've been thinking we should
switch to a mode in which the hashtable is maintained live altogether.
![]() |
Assignee | |
Comment 1•20 years ago
|
||
This makes us switch to a live ID table once we've had 128 misses for
GetElementById in this document.
That said, perhaps it would make sense to eliminate some of this complexity and
always have a live table?
Attachment #188265 -
Flags: superreview?(jst)
Attachment #188265 -
Flags: review?(jst)
Updated•20 years ago
|
OS: Linux → All
Hardware: PC → All
![]() |
Assignee | |
Updated•19 years ago
|
Attachment #188265 -
Flags: superreview?(jst)
Attachment #188265 -
Flags: review?(jst)
![]() |
Assignee | |
Comment 2•19 years ago
|
||
Attachment #188265 -
Attachment is obsolete: true
Attachment #194001 -
Flags: superreview?(jst)
Attachment #194001 -
Flags: review?(jst)
Comment 3•19 years ago
|
||
Comment on attachment 194001 [details] [diff] [review]
Updated to tip
+ PRBool IdTableIsLive() {
+ // live if we've had over 127 misses
+ return (mIdMissCount & 0x80) != 0;
+ }
Make that const, and isn't 127 sortof a high number here? How about 63?
- In nsHTMLDocument::UpdateIdTableEntry():
+ PRBool liveTable = IdTableIsLive();
+ PLDHashOperator op = liveTable ? PL_DHASH_ADD : PL_DHASH_LOOKUP;
IdAndNameMapEntry *entry =
NS_STATIC_CAST(IdAndNameMapEntry *,
PL_DHashTableOperate(&mIdAndNameHashTable, &aId,
- PL_DHASH_LOOKUP));
+ op));
- if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
+ if ((liveTable && entry) || PL_DHASH_ENTRY_IS_BUSY(entry))
PL_DHashTableOperate() can return a null entry for PL_DHASH_ADD if we're OOM,
you need to not do the PL_DHASH_ENTRY_IS_BUSY(entry) check if entry is null.
r+sr=jst
Attachment #194001 -
Flags: superreview?(jst)
Attachment #194001 -
Flags: superreview+
Attachment #194001 -
Flags: review?(jst)
Attachment #194001 -
Flags: review+
![]() |
Assignee | |
Comment 4•19 years ago
|
||
Assignee: general → bzbarsky
Attachment #194001 -
Attachment is obsolete: true
Status: NEW → ASSIGNED
![]() |
Assignee | |
Comment 5•19 years ago
|
||
Fix checked in to trunk.
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
Comment 6•19 years ago
|
||
Comment on attachment 195157 [details] [diff] [review]
Updated to comments
>+ PRBool liveTable = IdTableIsLive();
>+ PLDHashOperator op = liveTable ? PL_DHASH_ADD : PL_DHASH_LOOKUP;
> IdAndNameMapEntry *entry =
> NS_STATIC_CAST(IdAndNameMapEntry *,
> PL_DHashTableOperate(&mIdAndNameHashTable, &aId,
>- PL_DHASH_LOOKUP));
>+ op));
>
>- if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
>+ if (entry && (liveTable || PL_DHASH_ENTRY_IS_BUSY(entry))) {
> entry->mIdContent = aContent;
> }
If !entry, you should bail with OOM.
Do you really want to probe the table without adding if !liveTable? If so, you
could simplify the logic of the || expression to just
PL_DHASH_ENTRY_IS_BUSY(entry). If not, you don't need that || expression at
all.
/be
Comment 7•19 years ago
|
||
(In reply to comment #6)
> If not, you don't need that || expression at all.
By which I mean, always PL_DHASH_ADD. It's like a LOOKUP when the entry exists
(it doesn't disturb the entry).
/be
Comment 8•19 years ago
|
||
(In reply to comment #7)
> (In reply to comment #6)
> > If not, you don't need that || expression at all.
>
> By which I mean, always PL_DHASH_ADD. It's like a LOOKUP when the entry exists
> (it doesn't disturb the entry).
So bz pointed out the obvious, that we don't want to add unconditionally. So my
"then" clause ("you could simplify the logic of the || expression to just
PL_DHASH_ENTRY_IS_BUSY(entry)") applies, because if ADD succeeds (does not fail
with OOM and return null), it returns a busy entry pointer.
/be
![]() |
Assignee | |
Comment 9•19 years ago
|
||
I just checked this in with r+sr=brendan:
- if (entry && (liveTable || PL_DHASH_ENTRY_IS_BUSY(entry))) {
+ if (!entry) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
![]() |
Assignee | |
Comment 10•19 years ago
|
||
Fixed on trunk.
![]() |
Assignee | |
Comment 11•18 years ago
|
||
Not exactly sure how to write a decent test for this...
Flags: in-testsuite?
Updated•6 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•