Changeset 282227 in webkit
- Timestamp:
- Sep 9, 2021, 11:04:27 AM (5 years ago)
- Location:
- branches/safari-612-branch/Source/WebCore
- Files:
-
- 2 added
- 6 edited
-
ChangeLog (modified) (1 diff)
-
Sources.txt (modified) (1 diff)
-
WebCore.xcodeproj/project.pbxproj (modified) (4 diffs)
-
html/parser/AtomHTMLToken.h (modified) (4 diffs)
-
html/parser/HTMLAtomStringCache.cpp (added)
-
html/parser/HTMLAtomStringCache.h (added)
-
page/MemoryRelease.cpp (modified) (2 diffs)
-
page/cocoa/MemoryReleaseCocoa.mm (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-612-branch/Source/WebCore/ChangeLog
r281904 r282227 1 2021-09-09 Russell Epstein <repstein@apple.com> 2 3 Cherry-pick r282142. rdar://problem/82931317 4 5 Add a fast path for atomizing strings when parsing HTML 6 https://bugs.webkit.org/show_bug.cgi?id=229907 7 rdar://82854612 8 9 Reviewed by Yusuke Suzuki and Darin Adler. 10 11 On various subtests in Speedometer 2, a nontrivial amount of time is spent mapping raw UChar data vectors into 12 AtomStrings while parsing HTML tag names, attribute names and attribute values. Most of this happens underneath 13 the AtomHTMLToken constructor, which computes a hash for each string in the process of adding it to the atom 14 string table; the time it takes to compute this string hash increases linearly with the length of the string. 15 16 However, over the course of the benchmark, the vast majority of AtomStrings created out of tag names, attribute 17 names and attribute values are both: 18 19 (1) Strings that we've already recently atomized, and 20 (2) Usually distinguishable from other atom strings based solely on their first character, last character, and 21 overall string length. 22 23 As such, it's possible to slightly improve string atomization performance in this particular case (i.e. parsing 24 HTML) by maintaining a smaller cache of recently atomized AtomStrings that we index using a simple, constant- 25 time hash function that considers only the first character, last character, and length of the string. In terms 26 of the cache hit rate in this AtomString cache, the default string hashing algorithm only barely outperforms 27 this simple hash function on Speedometer (i.e., a cache hit rate of 99.24% using the default hash algorithm vs. 28 99.15% using the "first/last character and length" hash). 29 30 Using this technique, we can get a significant performance improvement on Speedometer by introducing two small, 31 fixed-size (512 capacity) AtomString tables: one to hold tag names and attribute names, and another to hold 32 attribute values (which seems to contain a much larger set of unique strings); we additionally use the cheap "2- 33 char & length" hash algorithm described above to index into these fixed-size tables. 34 35 This allows us to more efficiently atomize not only known tag and attribute names, but also custom element tag 36 names and attribute names and values that tend to appear frequently in markup (e.g. due to using certain 37 JavaScript frameworks that get and set HTML attributes). 38 39 * Sources.txt: 40 * WebCore.xcodeproj/project.pbxproj: 41 * html/parser/AtomHTMLToken.h: 42 (WebCore::AtomHTMLToken::initializeAttributes): 43 (WebCore::AtomHTMLToken::AtomHTMLToken): 44 * html/parser/HTMLAtomStringCache.cpp: Added. 45 (WebCore::HTMLAtomStringCache::cache): 46 * html/parser/HTMLAtomStringCache.h: Added. 47 48 Add a helper class that exposes three static inline helper methods: `makeTagOrAttributeName` and 49 `makeAttributeValue`, which return AtomStrings for the given `Vector<UChar>` (consulting the corresponding 50 cache if possible); and `clear`, which empties all cached atom strings. 51 52 (WebCore::HTMLAtomStringCache::makeTagOrAttributeName): 53 (WebCore::HTMLAtomStringCache::makeAttributeValue): 54 (WebCore::HTMLAtomStringCache::clear): 55 (WebCore::HTMLAtomStringCache::make): 56 57 Additionally add an upper length limit for characters that we include in this cache; in practice, longer strings 58 tend to be repeatedly atomized less frequently than shorter strings. The 36-character limit also allows for 59 frequently-parsed (and atomized) UUIDs to be cached. 60 61 (WebCore::HTMLAtomStringCache::cacheSlot): 62 63 This hashing algorithm was inspired by `calculateWithTwoCharacters`, but with constants specifically chosen to 64 minimize collisions between common HTML tag and attribute names. 65 66 * page/MemoryRelease.cpp: 67 (WebCore::releaseNoncriticalMemory): 68 * page/cocoa/MemoryReleaseCocoa.mm: 69 (WebCore::jettisonExpensiveObjectsOnTopLevelNavigation): 70 71 Add logic to clear the HTML atom string cache upon receiving a low memory warning, and upon top-level 72 navigation. 73 74 75 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282142 268f45cc-cd09-0410-ab3c-d52691b4dbfc 76 77 2021-09-08 Wenson Hsieh <wenson_hsieh@apple.com> 78 79 Add a fast path for atomizing strings when parsing HTML 80 https://bugs.webkit.org/show_bug.cgi?id=229907 81 rdar://82854612 82 83 Reviewed by Yusuke Suzuki and Darin Adler. 84 85 On various subtests in Speedometer 2, a nontrivial amount of time is spent mapping raw UChar data vectors into 86 AtomStrings while parsing HTML tag names, attribute names and attribute values. Most of this happens underneath 87 the AtomHTMLToken constructor, which computes a hash for each string in the process of adding it to the atom 88 string table; the time it takes to compute this string hash increases linearly with the length of the string. 89 90 However, over the course of the benchmark, the vast majority of AtomStrings created out of tag names, attribute 91 names and attribute values are both: 92 93 (1) Strings that we've already recently atomized, and 94 (2) Usually distinguishable from other atom strings based solely on their first character, last character, and 95 overall string length. 96 97 As such, it's possible to slightly improve string atomization performance in this particular case (i.e. parsing 98 HTML) by maintaining a smaller cache of recently atomized AtomStrings that we index using a simple, constant- 99 time hash function that considers only the first character, last character, and length of the string. In terms 100 of the cache hit rate in this AtomString cache, the default string hashing algorithm only barely outperforms 101 this simple hash function on Speedometer (i.e., a cache hit rate of 99.24% using the default hash algorithm vs. 102 99.15% using the "first/last character and length" hash). 103 104 Using this technique, we can get a significant performance improvement on Speedometer by introducing two small, 105 fixed-size (512 capacity) AtomString tables: one to hold tag names and attribute names, and another to hold 106 attribute values (which seems to contain a much larger set of unique strings); we additionally use the cheap "2- 107 char & length" hash algorithm described above to index into these fixed-size tables. 108 109 This allows us to more efficiently atomize not only known tag and attribute names, but also custom element tag 110 names and attribute names and values that tend to appear frequently in markup (e.g. due to using certain 111 JavaScript frameworks that get and set HTML attributes). 112 113 * Sources.txt: 114 * WebCore.xcodeproj/project.pbxproj: 115 * html/parser/AtomHTMLToken.h: 116 (WebCore::AtomHTMLToken::initializeAttributes): 117 (WebCore::AtomHTMLToken::AtomHTMLToken): 118 * html/parser/HTMLAtomStringCache.cpp: Added. 119 (WebCore::HTMLAtomStringCache::cache): 120 * html/parser/HTMLAtomStringCache.h: Added. 121 122 Add a helper class that exposes three static inline helper methods: `makeTagOrAttributeName` and 123 `makeAttributeValue`, which return AtomStrings for the given `Vector<UChar>` (consulting the corresponding 124 cache if possible); and `clear`, which empties all cached atom strings. 125 126 (WebCore::HTMLAtomStringCache::makeTagOrAttributeName): 127 (WebCore::HTMLAtomStringCache::makeAttributeValue): 128 (WebCore::HTMLAtomStringCache::clear): 129 (WebCore::HTMLAtomStringCache::make): 130 131 Additionally add an upper length limit for characters that we include in this cache; in practice, longer strings 132 tend to be repeatedly atomized less frequently than shorter strings. The 36-character limit also allows for 133 frequently-parsed (and atomized) UUIDs to be cached. 134 135 (WebCore::HTMLAtomStringCache::cacheSlot): 136 137 This hashing algorithm was inspired by `calculateWithTwoCharacters`, but with constants specifically chosen to 138 minimize collisions between common HTML tag and attribute names. 139 140 * page/MemoryRelease.cpp: 141 (WebCore::releaseNoncriticalMemory): 142 * page/cocoa/MemoryReleaseCocoa.mm: 143 (WebCore::jettisonExpensiveObjectsOnTopLevelNavigation): 144 145 Add logic to clear the HTML atom string cache upon receiving a low memory warning, and upon top-level 146 navigation. 147 1 148 2021-09-01 Russell Epstein <repstein@apple.com> 2 149 -
branches/safari-612-branch/Source/WebCore/Sources.txt
r281263 r282227 1303 1303 html/forms/FileIconLoader.cpp 1304 1304 html/parser/CSSPreloadScanner.cpp 1305 html/parser/HTMLAtomStringCache.cpp 1305 1306 html/parser/HTMLConstructionSite.cpp 1306 1307 html/parser/HTMLDocumentParser.cpp -
branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r281263 r282227 5385 5385 F48D2AA52159740D00C6752B /* ColorCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2AA32159740D00C6752B /* ColorCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5386 5386 F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F49786871FF45FA500E060AB /* PasteboardItemInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5387 F4B0018926E7F21F006EAABE /* HTMLAtomStringCache.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B0018726E7F21F006EAABE /* HTMLAtomStringCache.h */; }; 5387 5388 F4B2A909265030BA009E7286 /* DataDetectorHighlight.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B2A90626502BA0009E7286 /* DataDetectorHighlight.h */; }; 5388 5389 F4B422C4220C0568009E1E7D /* DOMPasteAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B422C2220C0000009E1E7D /* DOMPasteAccess.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 16556 16557 F49786871FF45FA500E060AB /* PasteboardItemInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardItemInfo.h; sourceTree = "<group>"; }; 16557 16558 F49E98E421DEE6C1009AE55E /* EditAction.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = EditAction.cpp; sourceTree = "<group>"; }; 16559 F4B0018726E7F21F006EAABE /* HTMLAtomStringCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLAtomStringCache.h; sourceTree = "<group>"; }; 16560 F4B0018826E7F21F006EAABE /* HTMLAtomStringCache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLAtomStringCache.cpp; sourceTree = "<group>"; }; 16558 16561 F4B2A90626502BA0009E7286 /* DataDetectorHighlight.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataDetectorHighlight.h; sourceTree = "<group>"; }; 16559 16562 F4B2A90826502BC0009E7286 /* DataDetectorHighlight.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DataDetectorHighlight.mm; sourceTree = "<group>"; }; … … 24036 24039 977B3849122883E900B81FF8 /* CSSPreloadScanner.cpp */, 24037 24040 977B384A122883E900B81FF8 /* CSSPreloadScanner.h */, 24041 F4B0018826E7F21F006EAABE /* HTMLAtomStringCache.cpp */, 24042 F4B0018726E7F21F006EAABE /* HTMLAtomStringCache.h */, 24038 24043 977B384B122883E900B81FF8 /* HTMLConstructionSite.cpp */, 24039 24044 977B384C122883E900B81FF8 /* HTMLConstructionSite.h */, … … 32141 32146 A8CFF7AB0A156978000A4234 /* HTMLAnchorElement.h in Headers */, 32142 32147 A8EA7D2E0A19385500A8EF5F /* HTMLAreaElement.h in Headers */, 32148 F4B0018926E7F21F006EAABE /* HTMLAtomStringCache.h in Headers */, 32143 32149 7C5F28FC1A827D8400C0F31F /* HTMLAttachmentElement.h in Headers */, 32144 32150 E44613A20CD6331000FADA75 /* HTMLAudioElement.h in Headers */, -
branches/safari-612-branch/Source/WebCore/html/parser/AtomHTMLToken.h
r280199 r282227 27 27 #pragma once 28 28 29 #include "HTMLAtomStringCache.h" 29 30 #include "HTMLToken.h" 30 31 … … 203 204 continue; 204 205 205 AtomString localName(attribute.name);206 auto localName = HTMLAtomStringCache::makeTagOrAttributeName(attribute.name); 206 207 207 208 // FIXME: This is N^2 for the number of attributes. 208 209 if (!hasAttribute(m_attributes, localName)) 209 m_attributes.uncheckedAppend(Attribute(QualifiedName(nullAtom(), localName, nullAtom()), AtomString(attribute.value)));210 m_attributes.uncheckedAppend(Attribute(QualifiedName(nullAtom(), localName, nullAtom()), HTMLAtomStringCache::makeAttributeValue(attribute.value))); 210 211 } 211 212 } … … 219 220 return; 220 221 case HTMLToken::DOCTYPE: 221 m_name = AtomString(token.name());222 m_name = HTMLAtomStringCache::makeTagOrAttributeName(token.name()); 222 223 m_doctypeData = token.releaseDoctypeData(); 223 224 return; … … 227 228 case HTMLToken::EndTag: 228 229 m_selfClosing = token.selfClosing(); 229 m_name = AtomString(token.name());230 m_name = HTMLAtomStringCache::makeTagOrAttributeName(token.name()); 230 231 initializeAttributes(token.attributes()); 231 232 return; -
branches/safari-612-branch/Source/WebCore/page/MemoryRelease.cpp
r275428 r282227 39 39 #include "Frame.h" 40 40 #include "GCController.h" 41 #include "HTMLAtomStringCache.h" 41 42 #include "HTMLMediaElement.h" 42 43 #include "InlineStyleSheetOwner.h" … … 86 87 87 88 InlineStyleSheetOwner::clearCache(); 89 HTMLAtomStringCache::clear(); 88 90 } 89 91 -
branches/safari-612-branch/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm
r271526 r282227 29 29 #import "FontFamilySpecificationCoreText.h" 30 30 #import "GCController.h" 31 #import "HTMLAtomStringCache.h" 31 32 #import "IOSurfacePool.h" 32 33 #import "LayerPool.h" … … 84 85 void jettisonExpensiveObjectsOnTopLevelNavigation() 85 86 { 86 #if PLATFORM(IOS_FAMILY)87 87 // Protect against doing excessive jettisoning during repeated navigations. 88 88 const auto minimumTimeSinceNavigation = 2_s; … … 96 96 return; 97 97 98 #if PLATFORM(IOS_FAMILY) 98 99 // Throw away linked JS code. Linked code is tied to a global object and is not reusable. 99 100 // The immediate memory savings outweigh the cost of recompilation in case we go back again. 100 101 GCController::singleton().deleteAllLinkedCode(JSC::DeleteAllCodeIfNotCollecting); 101 102 #endif 103 104 HTMLAtomStringCache::clear(); 102 105 } 103 106
Note:
See TracChangeset
for help on using the changeset viewer.