diff options
author | Andreas Kling <kling@serenityos.org> | 2023-03-30 11:18:50 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-03-30 14:12:07 +0200 |
commit | 1f166b3a15b38e1ee065905d4e99401ba39b9f8e (patch) | |
tree | f1189093bba2c2d2d0cc6db5fae4838d6af65b59 /Userland/Libraries/LibWeb/CSS | |
parent | d4b2544dc55785f7233f84943ae579be31e43e5e (diff) | |
download | serenity-1f166b3a15b38e1ee065905d4e99401ba39b9f8e.zip |
LibWeb: Don't re-sort StyleSheetList on every new sheet insertion
This was causing a huge slowdown when loading some pages with weirdly
huge number of style sheets. For example, amazon.com has over 200 style
elements, which meant we had to resort the StyleSheetList 200 times.
(And sorting itself was slow because it has to compare DOM positions.)
Instead of sorting, we now look for the correct insertion point when
adding new style sheets, and we start the search from the end, which is
where style sheets are typically added in the vast majority of cases.
This removes a 600ms time sink when loading Amazon on my machine! :^)
Diffstat (limited to 'Userland/Libraries/LibWeb/CSS')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp b/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp index 8c0abc6dcc..2ba3d57c92 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp @@ -15,9 +15,25 @@ namespace Web::CSS { void StyleSheetList::add_sheet(CSSStyleSheet& sheet) { sheet.set_style_sheet_list({}, this); - m_sheets.append(sheet); - sort_sheets(); + if (m_sheets.is_empty()) { + // This is the first sheet, append it to the list. + m_sheets.append(sheet); + } else { + // We have sheets from before. Insert the new sheet in the correct position (DOM tree order). + bool did_insert = false; + for (ssize_t i = m_sheets.size() - 1; i >= 0; --i) { + auto& existing_sheet = *m_sheets[i]; + auto position = existing_sheet.owner_node()->compare_document_position(sheet.owner_node()); + if (position & DOM::Node::DocumentPosition::DOCUMENT_POSITION_FOLLOWING) { + m_sheets.insert(i + 1, sheet); + did_insert = true; + break; + } + } + if (!did_insert) + m_sheets.prepend(sheet); + } if (sheet.rules().length() == 0) { // NOTE: If the added sheet has no rules, we don't have to invalidate anything. |