mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-04 15:19:42 +00:00
LibWeb: Avoid expensive Vector filtering in event loop
Instead of collecting all documents in a big vector and then filtering the vector (twice!) with remove_all_matching(), we now pass a filter callback to documents_in_this_event_loop_matching() and avoid all the extra shuffling work. Saw this stuff hogging ~20% of CPU time when profiling a WebContent process in the middle of a WPT run.
This commit is contained in:
parent
eafa70331d
commit
26f32b11f9
Notes:
github-actions[bot]
2024-11-24 16:18:45 +00:00
Author: https://github.com/awesomekling
Commit: 26f32b11f9
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2548
2 changed files with 23 additions and 17 deletions
|
@ -260,30 +260,28 @@ void EventLoop::update_the_rendering()
|
||||||
// FIXME: 1. Let frameTimestamp be eventLoop's last render opportunity time.
|
// FIXME: 1. Let frameTimestamp be eventLoop's last render opportunity time.
|
||||||
|
|
||||||
// FIXME: 2. Let docs be all fully active Document objects whose relevant agent's event loop is eventLoop, sorted arbitrarily except that the following conditions must be met:
|
// FIXME: 2. Let docs be all fully active Document objects whose relevant agent's event loop is eventLoop, sorted arbitrarily except that the following conditions must be met:
|
||||||
auto docs = documents_in_this_event_loop();
|
|
||||||
docs.remove_all_matching([&](auto& document) {
|
|
||||||
return !document->is_fully_active();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Filter non-renderable documents: Remove from docs any Document object doc for which any of the following are true:
|
// 3. Filter non-renderable documents: Remove from docs any Document object doc for which any of the following are true:
|
||||||
docs.remove_all_matching([&](auto const& document) {
|
auto docs = documents_in_this_event_loop_matching([&](auto const& document) {
|
||||||
auto navigable = document->navigable();
|
if (!document.is_fully_active())
|
||||||
if (!navigable)
|
return false;
|
||||||
return true;
|
|
||||||
|
|
||||||
// FIXME: doc is render-blocked;
|
// FIXME: doc is render-blocked;
|
||||||
|
|
||||||
// doc's visibility state is "hidden";
|
// doc's visibility state is "hidden";
|
||||||
if (document->hidden())
|
if (document.hidden())
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
// FIXME: doc's rendering is suppressed for view transitions; or
|
// FIXME: doc's rendering is suppressed for view transitions; or
|
||||||
|
|
||||||
|
auto navigable = document.navigable();
|
||||||
|
if (!navigable)
|
||||||
|
return false;
|
||||||
|
|
||||||
// doc's node navigable doesn't currently have a rendering opportunity.
|
// doc's node navigable doesn't currently have a rendering opportunity.
|
||||||
if (!navigable->has_a_rendering_opportunity())
|
if (!navigable->has_a_rendering_opportunity())
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: 4. Unnecessary rendering: Remove from docs any Document object doc for which all of the following are true:
|
// FIXME: 4. Unnecessary rendering: Remove from docs any Document object doc for which all of the following are true:
|
||||||
|
@ -515,18 +513,25 @@ void EventLoop::perform_a_microtask_checkpoint()
|
||||||
// FIXME: 8. Record timing info for microtask checkpoint.
|
// FIXME: 8. Record timing info for microtask checkpoint.
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<GC::Root<DOM::Document>> EventLoop::documents_in_this_event_loop() const
|
Vector<GC::Root<DOM::Document>> EventLoop::documents_in_this_event_loop_matching(auto callback) const
|
||||||
{
|
{
|
||||||
Vector<GC::Root<DOM::Document>> documents;
|
Vector<GC::Root<DOM::Document>> documents;
|
||||||
for (auto& document : m_documents) {
|
for (auto& document : m_documents) {
|
||||||
VERIFY(document);
|
VERIFY(document);
|
||||||
if (document->is_decoded_svg())
|
if (document->is_decoded_svg())
|
||||||
continue;
|
continue;
|
||||||
|
if (!callback(*document))
|
||||||
|
continue;
|
||||||
documents.append(GC::make_root(*document));
|
documents.append(GC::make_root(*document));
|
||||||
}
|
}
|
||||||
return documents;
|
return documents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<GC::Root<DOM::Document>> EventLoop::documents_in_this_event_loop() const
|
||||||
|
{
|
||||||
|
return documents_in_this_event_loop_matching([](auto&) { return true; });
|
||||||
|
}
|
||||||
|
|
||||||
void EventLoop::register_document(Badge<DOM::Document>, DOM::Document& document)
|
void EventLoop::register_document(Badge<DOM::Document>, DOM::Document& document)
|
||||||
{
|
{
|
||||||
m_documents.append(&document);
|
m_documents.append(&document);
|
||||||
|
@ -568,8 +573,7 @@ void EventLoop::unregister_environment_settings_object(Badge<EnvironmentSettings
|
||||||
Vector<GC::Root<HTML::Window>> EventLoop::same_loop_windows() const
|
Vector<GC::Root<HTML::Window>> EventLoop::same_loop_windows() const
|
||||||
{
|
{
|
||||||
Vector<GC::Root<HTML::Window>> windows;
|
Vector<GC::Root<HTML::Window>> windows;
|
||||||
for (auto& document : documents_in_this_event_loop()) {
|
for (auto& document : documents_in_this_event_loop_matching([](auto& document) { return document.is_fully_active(); })) {
|
||||||
if (document->is_fully_active())
|
|
||||||
windows.append(GC::make_root(document->window()));
|
windows.append(GC::make_root(document->window()));
|
||||||
}
|
}
|
||||||
return windows;
|
return windows;
|
||||||
|
|
|
@ -95,6 +95,8 @@ private:
|
||||||
|
|
||||||
virtual void visit_edges(Visitor&) override;
|
virtual void visit_edges(Visitor&) override;
|
||||||
|
|
||||||
|
[[nodiscard]] Vector<GC::Root<DOM::Document>> documents_in_this_event_loop_matching(auto callback) const;
|
||||||
|
|
||||||
void update_the_rendering();
|
void update_the_rendering();
|
||||||
|
|
||||||
Type m_type { Type::Window };
|
Type m_type { Type::Window };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue