topPrivatelyControlledDomain is slow
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Oct 2018 10:20:34 +0000 (10:20 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Oct 2018 10:20:34 +0000 (10:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190792

Reviewed by Alex Christensen and Chris Dumez.

It calls into some slowish CFNetwork code and ends up showing up in profiles.

* platform/mac/PublicSuffixMac.mm:
(WebCore::topPrivatelyControlledDomain):

Add a cache that avoids calls into frameworks.

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

Source/WebCore/ChangeLog
Source/WebCore/platform/mac/PublicSuffixMac.mm

index 1c76e20..3acb81c 100644 (file)
@@ -1,3 +1,17 @@
+2018-10-22  Antti Koivisto  <antti@apple.com>
+
+        topPrivatelyControlledDomain is slow
+        https://bugs.webkit.org/show_bug.cgi?id=190792
+
+        Reviewed by Alex Christensen and Chris Dumez.
+
+        It calls into some slowish CFNetwork code and ends up showing up in profiles.
+
+        * platform/mac/PublicSuffixMac.mm:
+        (WebCore::topPrivatelyControlledDomain):
+
+        Add a cache that avoids calls into frameworks.
+
 2018-10-22  Jer Noble  <jer.noble@apple.com>
 
         Use WeakPtr and GenericTaskQueue within ObjC classes used by MediaPlayerPrivateAVFoundationObjC
index 2303817..e2edb87 100644 (file)
@@ -31,6 +31,8 @@
 #import "URL.h"
 #import "WebCoreNSURLExtras.h"
 #import <pal/spi/cf/CFNetworkSPI.h>
+#import <wtf/HashMap.h>
+#import <wtf/text/StringHash.h>
 
 namespace WebCore {
 
@@ -43,22 +45,37 @@ bool isPublicSuffix(const String& domain)
 
 String topPrivatelyControlledDomain(const String& domain)
 {
-    if (URL::hostIsIPAddress(domain))
-        return domain;
-
+    if (domain.isEmpty())
+        return { };
     if (!domain.isAllASCII())
         return domain;
-    
-    const auto& lowercaseDomain = domain.convertToASCIILowercase();
-    if (lowercaseDomain == "localhost")
-        return lowercaseDomain;
-
-    size_t separatorPosition;
-    for (unsigned labelStart = 0; (separatorPosition = lowercaseDomain.find('.', labelStart)) != notFound; labelStart = separatorPosition + 1) {
-        if (isPublicSuffix(lowercaseDomain.substring(separatorPosition + 1)))
-            return lowercaseDomain.substring(labelStart);
-    }
-    return String();
+
+    static NeverDestroyed<HashMap<String, String, ASCIICaseInsensitiveHash>> cache;
+    static Lock cacheLock;
+
+    auto isolatedDomain = domain.isolatedCopy();
+
+    auto locker = holdLock(cacheLock);
+
+    constexpr auto maximumSizeToPreventUnlimitedGrowth = 128;
+    if (cache.get().size() == maximumSizeToPreventUnlimitedGrowth)
+        cache.get().clear();
+
+    return cache.get().ensure(isolatedDomain, [&isolatedDomain] {
+        const auto lowercaseDomain = isolatedDomain.convertToASCIILowercase();
+        if (lowercaseDomain == "localhost")
+            return lowercaseDomain;
+
+        if (URL::hostIsIPAddress(lowercaseDomain))
+            return lowercaseDomain;
+
+        size_t separatorPosition;
+        for (unsigned labelStart = 0; (separatorPosition = lowercaseDomain.find('.', labelStart)) != notFound; labelStart = separatorPosition + 1) {
+            if (isPublicSuffix(lowercaseDomain.substring(separatorPosition + 1)))
+                return lowercaseDomain.substring(labelStart);
+        }
+        return String();
+    }).iterator->value.isolatedCopy();
 }
 
 String decodeHostName(const String& domain)