RESOLVED FIXED273959
AX: it's inefficient to put large object types in AXPropertyValueVariant
https://bugs.webkit.org/show_bug.cgi?id=273959
Summary AX: it's inefficient to put large object types in AXPropertyValueVariant
Dominic Mazzoni
Reported 2024-05-09 10:33:57 PDT
sizeof(AXPropertyValueVariant) is currently 88 bytes. If we take out URL and Path, it drops to 32 bytes, which is a very significant savings since we're storing lots of these for every isolated tree node. Wrapping URL and Path in shared_ptr is an easy workaround. That way only the pointer is stored in the variant. We can't use unique_ptr because we store the variant in a HashMap that requires it to be copyable. Another alternative for URL would be to store it as a String and then parse it into a URL when needed.
Attachments
Patch (8.71 KB, patch)
2024-05-09 10:40 PDT, Dominic Mazzoni
no flags
Patch (8.82 KB, patch)
2024-05-16 14:32 PDT, Dominic Mazzoni
no flags
Radar WebKit Bug Importer
Comment 1 2024-05-09 10:34:08 PDT
Dominic Mazzoni
Comment 2 2024-05-09 10:40:55 PDT
Andres Gonzalez
Comment 3 2024-05-10 08:53:14 PDT
(In reply to Dominic Mazzoni from comment #2) > Created attachment 471341 [details] > Patch diff --git a/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp b/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp index 1cf2c43bbce0..1ada0332733d 100644 --- a/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp +++ b/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp @@ -156,7 +156,7 @@ void AXIsolatedObject::initializeProperties(const Ref<AccessibilityObject>& axOb setProperty(AXPropertyName::ExpandedTextValue, object.expandedTextValue().isolatedCopy()); setProperty(AXPropertyName::SupportsExpandedTextValue, object.supportsExpandedTextValue()); setProperty(AXPropertyName::ValueAutofillButtonType, static_cast<int>(object.valueAutofillButtonType())); - setProperty(AXPropertyName::URL, object.url().isolatedCopy()); + setProperty(AXPropertyName::URL, std::make_shared<URL>(object.url().isolatedCopy())); setProperty(AXPropertyName::AccessKey, object.accessKey().isolatedCopy()); setProperty(AXPropertyName::AutoCompleteValue, object.autoCompleteValue().isolatedCopy()); setProperty(AXPropertyName::ColorValue, object.colorValue()); @@ -166,7 +166,7 @@ void AXIsolatedObject::initializeProperties(const Ref<AccessibilityObject>& axOb setProperty(AXPropertyName::LiveRegionStatus, object.liveRegionStatus().isolatedCopy()); setProperty(AXPropertyName::LiveRegionRelevant, object.liveRegionRelevant().isolatedCopy()); setProperty(AXPropertyName::LiveRegionAtomic, object.liveRegionAtomic()); - setProperty(AXPropertyName::Path, object.elementPath()); + setProperty(AXPropertyName::Path, std::make_shared<Path>(object.elementPath())); setProperty(AXPropertyName::HasHighlighting, object.hasHighlighting()); setProperty(AXPropertyName::HasBoldFont, object.hasBoldFont()); setProperty(AXPropertyName::HasItalicFont, object.hasItalicFont()); @@ -462,7 +462,7 @@ void AXIsolatedObject::setProperty(AXPropertyName propertyName, AXPropertyValueV [](uint64_t typedValue) { return !typedValue; }, [](AccessibilityButtonState& typedValue) { return typedValue == AccessibilityButtonState::Off; }, [](Color& typedValue) { return typedValue == Color(); }, - [](URL& typedValue) { return typedValue == URL(); }, + [](std::optional<URL>& typedValue) { return !typedValue || *typedValue == URL(); }, AG: shouldn't this be shared_ptr? [](LayoutRect& typedValue) { return typedValue == LayoutRect(); }, [](IntPoint& typedValue) { return typedValue == IntPoint(); }, [](IntRect& typedValue) { return typedValue == IntRect(); }, @@ -476,7 +476,7 @@ void AXIsolatedObject::setProperty(AXPropertyName propertyName, AXPropertyValueV [](Vector<AXID>& typedValue) { return typedValue.isEmpty(); }, [](Vector<std::pair<AXID, AXID>>& typedValue) { return typedValue.isEmpty(); }, [](Vector<String>& typedValue) { return typedValue.isEmpty(); }, - [](Path& typedValue) { return typedValue.isEmpty(); }, + [](std::optional<Path>& typedValue) { return !typedValue || typedValue->isEmpty(); }, AG: shouldn't this be shared_ptr? [](OptionSet<AXAncestorFlag>& typedValue) { return typedValue.isEmpty(); }, #if PLATFORM(COCOA) [](RetainPtr<NSAttributedString>& typedValue) { return !typedValue; }, @@ -953,7 +953,7 @@ URL AXIsolatedObject::urlAttributeValue(AXPropertyName propertyName) const { auto value = m_propertyMap.get(propertyName); return WTF::switchOn(value, - [] (URL& typedValue) -> URL { return typedValue; }, + [] (std::shared_ptr<URL>& typedValue) -> URL { return *typedValue.get(); }, AG: maybe we should assert here that typedValue is not null before deref-ing. [] (auto&) { return URL(); } ); } @@ -962,7 +962,7 @@ Path AXIsolatedObject::pathAttributeValue(AXPropertyName propertyName) const { auto value = m_propertyMap.get(propertyName); return WTF::switchOn(value, - [] (Path& typedValue) -> Path { return typedValue; }, + [] (std::shared_ptr<Path>& typedValue) -> Path { return *typedValue.get(); }, AG: maybe we should assert here that typedValue is not null before deref-ing. [] (auto&) { return Path(); } ); }
Dominic Mazzoni
Comment 4 2024-05-16 14:32:37 PDT
Dominic Mazzoni
Comment 5 2024-05-16 14:35:54 PDT
I confirmed that tests that cover URL and Path pass in ITM, hopefully this should be ready to go. > AG: shouldn't this be shared_ptr? Yes, good catch. As you can see, I experimented with std::optional, but it didn't give any memory savings. > AG: maybe we should assert here that typedValue is not null before deref-ing. Good idea, done.
chris fleizach
Comment 6 2024-05-16 23:18:40 PDT
Comment on attachment 471424 [details] Patch nice work!
EWS
Comment 7 2024-05-17 17:25:08 PDT
Committed 278940@main (f4cd05fb5b19): <https://commits.webkit.org/278940@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 471424 [details].
Note You need to log in before you can comment on or make changes to this bug.