[PSON] Prewarm system fallback fonts
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2018 16:02:35 +0000 (16:02 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Oct 2018 16:02:35 +0000 (16:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190517

Reviewed by Ryosuke Niwa.

This seems to be ~2% progression in PSON PLT4 with large (40ms+) improvements on some pages
after process swaps.

* page/PrewarmInformation.h:
(WebCore::PrewarmInformation::encode const):
(WebCore::PrewarmInformation::decode):
* page/ProcessWarming.cpp:
(WebCore::ProcessWarming::collectPrewarmInformation):
(WebCore::ProcessWarming::prewarmWithInformation):
* platform/graphics/FontCache.cpp:
(WebCore::FontCache::collectPrewarmInformation const):
(WebCore::FontCache::prewarm):
* platform/graphics/FontCache.h:
(WebCore::FontCache::PrewarmInformation::isolatedCopy const):
(WebCore::FontCache::PrewarmInformation::encode const):
(WebCore::FontCache::PrewarmInformation::decode):

Make font cache prewarm information a struct with encode/decode support and move it into FontCache scope.

* platform/graphics/cocoa/FontCacheCoreText.cpp:
(WebCore::FontDatabase::collectionForFamily):
(WebCore::FontCache::systemFallbackForCharacters):

Collect the names of fonts that end up needing character specific system fallbacks.

(WebCore::FontCache::collectPrewarmInformation const):

Include them into prewarm information.

(WebCore::FontCache::prewarm):

Invoking CTFontCreateForCharactersWithLanguage for the correct named font seems sufficient to fully
prewarm it for fallbacks (independent of size, locale or other characteristics).
Any future calls to systemFallbackForCharacters are fast.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237116 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/page/PrewarmInformation.h
Source/WebCore/page/ProcessWarming.cpp
Source/WebCore/platform/graphics/FontCache.cpp
Source/WebCore/platform/graphics/FontCache.h
Source/WebCore/platform/graphics/cocoa/FontCacheCoreText.cpp

index 10d047a..78f2237 100644 (file)
@@ -1,3 +1,45 @@
+2018-10-15  Antti Koivisto  <antti@apple.com>
+
+        [PSON] Prewarm system fallback fonts
+        https://bugs.webkit.org/show_bug.cgi?id=190517
+
+        Reviewed by Ryosuke Niwa.
+
+        This seems to be ~2% progression in PSON PLT4 with large (40ms+) improvements on some pages
+        after process swaps.
+
+        * page/PrewarmInformation.h:
+        (WebCore::PrewarmInformation::encode const):
+        (WebCore::PrewarmInformation::decode):
+        * page/ProcessWarming.cpp:
+        (WebCore::ProcessWarming::collectPrewarmInformation):
+        (WebCore::ProcessWarming::prewarmWithInformation):
+        * platform/graphics/FontCache.cpp:
+        (WebCore::FontCache::collectPrewarmInformation const):
+        (WebCore::FontCache::prewarm):
+        * platform/graphics/FontCache.h:
+        (WebCore::FontCache::PrewarmInformation::isolatedCopy const):
+        (WebCore::FontCache::PrewarmInformation::encode const):
+        (WebCore::FontCache::PrewarmInformation::decode):
+
+        Make font cache prewarm information a struct with encode/decode support and move it into FontCache scope.
+
+        * platform/graphics/cocoa/FontCacheCoreText.cpp:
+        (WebCore::FontDatabase::collectionForFamily):
+        (WebCore::FontCache::systemFallbackForCharacters):
+
+        Collect the names of fonts that end up needing character specific system fallbacks.
+
+        (WebCore::FontCache::collectPrewarmInformation const):
+
+        Include them into prewarm information.
+
+        (WebCore::FontCache::prewarm):
+
+        Invoking CTFontCreateForCharactersWithLanguage for the correct named font seems sufficient to fully
+        prewarm it for fallbacks (independent of size, locale or other characteristics).
+        Any future calls to systemFallbackForCharacters are fast.
+
 2018-10-15  Chris Dumez  <cdumez@apple.com>
 
         Restrict browsing context lookup by name to frames that are related to one another
index 6ce7226..1ba9892 100644 (file)
@@ -32,7 +32,7 @@
 namespace WebCore {
 
 struct WEBCORE_EXPORT PrewarmInformation {
-    FontPrewarmInformation font;
+    FontCache::PrewarmInformation fontCache;
 
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static std::optional<PrewarmInformation> decode(Decoder&);
@@ -41,17 +41,18 @@ struct WEBCORE_EXPORT PrewarmInformation {
 template<class Encoder>
 void PrewarmInformation::encode(Encoder& encoder) const
 {
-    encoder << font;
+    encoder << fontCache;
 }
 
 template<class Decoder>
 std::optional<PrewarmInformation> PrewarmInformation::decode(Decoder& decoder)
 {
-    PrewarmInformation prewarmInfo;
-    if (!decoder.decode(prewarmInfo.font))
+    std::optional<FontCache::PrewarmInformation> fontCachePrewarmInformation;
+    decoder >> fontCachePrewarmInformation;
+    if (!fontCachePrewarmInformation)
         return { };
 
-    return prewarmInfo;
+    return PrewarmInformation { WTFMove(*fontCachePrewarmInformation) };
 }
 
 }
index 48c1f52..b3d6a95 100644 (file)
@@ -88,14 +88,12 @@ void ProcessWarming::prewarmGlobally()
 
 WebCore::PrewarmInformation ProcessWarming::collectPrewarmInformation()
 {
-    PrewarmInformation info;
-    info.font = FontCache::singleton().collectPrewarmInformation();
-    return info;
+    return { FontCache::singleton().collectPrewarmInformation() };
 }
 
 void ProcessWarming::prewarmWithInformation(const PrewarmInformation& prewarmInfo)
 {
-    FontCache::singleton().prewarm(prewarmInfo.font);
+    FontCache::singleton().prewarm(prewarmInfo.fontCache);
 }
 
 }
index f98b9c5..8542ec7 100644 (file)
@@ -483,12 +483,12 @@ void FontCache::invalidate()
 
 #if !PLATFORM(COCOA)
 
-FontPrewarmInformation FontCache::collectPrewarmInformation() const
+FontCache::PrewarmInformation FontCache::collectPrewarmInformation() const
 {
     return { };
 }
 
-void FontCache::prewarm(const FontPrewarmInformation&)
+void FontCache::prewarm(const PrewarmInformation&)
 {
 }
 
index 62cd6db..396036a 100644 (file)
@@ -69,8 +69,6 @@ typedef IMLangFontLink IMLangFontLinkType;
 #endif
 #endif
 
-using FontPrewarmInformation = Vector<String>;
-
 // This key contains the FontDescription fields other than family that matter when fetching FontDatas (platform fonts).
 struct FontDescriptionKey {
     FontDescriptionKey() = default;
@@ -239,8 +237,18 @@ public:
     bool shouldMockBoldSystemFontForAccessibility() const { return m_shouldMockBoldSystemFontForAccessibility; }
     void setShouldMockBoldSystemFontForAccessibility(bool shouldMockBoldSystemFontForAccessibility) { m_shouldMockBoldSystemFontForAccessibility = shouldMockBoldSystemFontForAccessibility; }
 
-    FontPrewarmInformation collectPrewarmInformation() const;
-    void prewarm(const FontPrewarmInformation&);
+    struct PrewarmInformation {
+        Vector<String> seenFamilies;
+        Vector<String> fontNamesRequiringSystemFallback;
+
+        bool isEmpty() const;
+        PrewarmInformation isolatedCopy() const;
+
+        template<class Encoder> void encode(Encoder&) const;
+        template<class Decoder> static std::optional<PrewarmInformation> decode(Decoder&);
+    };
+    PrewarmInformation collectPrewarmInformation() const;
+    void prewarm(const PrewarmInformation&);
 
 private:
     FontCache();
@@ -266,6 +274,7 @@ private:
 
 #if PLATFORM(COCOA)
     ListHashSet<String> m_seenFamiliesForPrewarming;
+    ListHashSet<String> m_fontNamesRequiringSystemFallbackForPrewarming;
     RefPtr<WorkQueue> m_prewarmQueue;
 
     friend class ComplexTextController;
@@ -286,4 +295,34 @@ inline void FontCache::platformPurgeInactiveFontData()
 
 #endif
 
+
+inline bool FontCache::PrewarmInformation::isEmpty() const
+{
+    return seenFamilies.isEmpty() && fontNamesRequiringSystemFallback.isEmpty();
+}
+
+inline FontCache::PrewarmInformation FontCache::PrewarmInformation::isolatedCopy() const
+{
+    return { seenFamilies.isolatedCopy(), fontNamesRequiringSystemFallback.isolatedCopy() };
+}
+
+template<class Encoder>
+void FontCache::PrewarmInformation::encode(Encoder& encoder) const
+{
+    encoder << seenFamilies;
+    encoder << fontNamesRequiringSystemFallback;
+}
+
+template<class Decoder>
+std::optional<FontCache::PrewarmInformation> FontCache::PrewarmInformation::decode(Decoder& decoder)
+{
+    PrewarmInformation prewarmInformation;
+    if (!decoder.decode(prewarmInformation.seenFamilies))
+        return { };
+    if (!decoder.decode(prewarmInformation.fontNamesRequiringSystemFallback))
+        return { };
+
+    return prewarmInformation;
+}
+
 }
index 8727bce..d67287b 100644 (file)
@@ -916,7 +916,7 @@ public:
         }();
 
         std::lock_guard<Lock> locker(m_familyNameToFontDescriptorsLock);
-        return m_familyNameToFontDescriptors.add(folded.isolatedCopy(), installedFontFamily).iterator->value;
+        return m_familyNameToFontDescriptors.add(folded.isolatedCopy(), WTFMove(installedFontFamily)).iterator->value;
     }
 
     const InstalledFont& fontForPostScriptName(const AtomicString& postScriptName)
@@ -1366,8 +1366,14 @@ RefPtr<Font> FontCache::systemFallbackForCharacters(const FontDescription& descr
 #endif
 
     const FontPlatformData& platformData = originalFontData->platformData();
+
+    auto fullName = String(adoptCF(CTFontCopyFullName(platformData.font())).get());
+    if (!fullName.isEmpty())
+        m_fontNamesRequiringSystemFallbackForPrewarming.add(fullName);
+
     auto result = lookupFallbackFont(platformData.font(), description.weight(), description.locale(), characters, length);
     result = preparePlatformFont(result.get(), description, nullptr, nullptr, { }, description.computedSize());
+
     if (!result)
         return lastResortFallbackFont(description);
 
@@ -1519,18 +1525,14 @@ Ref<Font> FontCache::lastResortFallbackFont(const FontDescription& fontDescripti
     return fontForPlatformData(platformData);
 }
 
-FontPrewarmInformation FontCache::collectPrewarmInformation() const
+FontCache::PrewarmInformation FontCache::collectPrewarmInformation() const
 {
-    FontPrewarmInformation fontPrewarmInformation;
-    fontPrewarmInformation = copyToVector(m_seenFamiliesForPrewarming);
-    return fontPrewarmInformation;
+    return { copyToVector(m_seenFamiliesForPrewarming), copyToVector(m_fontNamesRequiringSystemFallbackForPrewarming) };
 }
 
-void FontCache::prewarm(const FontPrewarmInformation& fontPrewarmInformation)
+void FontCache::prewarm(const PrewarmInformation& prewarmInformation)
 {
-    auto& families = fontPrewarmInformation;
-
-    if (families.isEmpty())
+    if (prewarmInformation.isEmpty())
         return;
 
     if (!m_prewarmQueue)
@@ -1538,9 +1540,19 @@ void FontCache::prewarm(const FontPrewarmInformation& fontPrewarmInformation)
 
     auto& database = FontDatabase::singletonDisallowingUserInstalledFonts();
 
-    m_prewarmQueue->dispatch([&database, families = families.isolatedCopy()] {
-        for (auto& family : families)
+    m_prewarmQueue->dispatch([&database, prewarmInformation = prewarmInformation.isolatedCopy()] {
+        for (auto& family : prewarmInformation.seenFamilies)
             database.collectionForFamily(family);
+
+        for (auto& fontName : prewarmInformation.fontNamesRequiringSystemFallback) {
+            auto cfFontName = fontName.createCFString();
+            if (auto warmingFont = adoptCF(CTFontCreateWithName(cfFontName.get(), 0, nullptr))) {
+                // This is sufficient to warm CoreText caches for language and character specific fallbacks.
+                CFIndex coveredLength = 0;
+                UChar character = ' ';
+                auto fallbackWarmingFont = adoptCF(CTFontCreateForCharactersWithLanguage(warmingFont.get(), &character, 1, nullptr, &coveredLength));
+            }
+        }
     });
 }