From 1f166b3a15b38e1ee065905d4e99401ba39b9f8e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 30 Mar 2023 11:18:50 +0200 Subject: [PATCH] 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! :^) --- .../Libraries/LibWeb/CSS/StyleSheetList.cpp | 20 +++++++++++++++++-- 1 file 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.