Changeset 223860 in webkit


Ignore:
Timestamp:
Oct 23, 2017 3:37:33 PM (6 years ago)
Author:
Wenson Hsieh
Message:

[iOS] DocumentWriter::createDocument can spend ~100ms unnecessarily converting image UTIs to MIME types
https://bugs.webkit.org/show_bug.cgi?id=178618
<rdar://problem/35108852>

Reviewed by Said Abou-Hallawa.

Currently, in setting up a new Document, DocumentWriter::createDocument() always asks whether or not the
Document should be a PDF document by calling MIMETypeRegistry::isPDFMIMEType(), which forces lazy initialization
of every MIME type dictionary (e.g. image types, PDF types, JavaScript types, etc.). As evidenced by traces,
this can be an expensive operation on certain devices.

This patch implements two optimizations. First, we refactor the initializeSupportedImageMIMETypes() helper to
stop asking for MIMETypeForImageSourceType for each of the supported UTIs. This is because the known MIME types
corresponding to these hard-coded UTI types is a fixed set anyways, so we can simply iterate over a constant
array of MIME types and populate the supported image (and image resource) types. Also, add assertions to ensure
that we keep allowed image MIME types in sync with allowed image UTIs.

The second optimization removes initializeMIMETypeRegistry() altogether in favor of calling just the
initialize*MIMETypes() functions needed to ensure the information required. For instance, getPDFMIMETypes()
currently calls initializeMIMETypeRegistry() if the pdfMIMETypes dictionary doesn't exist, when it really only
needs to ensure that the pdfMIMETypes is initialized, for which initializePDFMIMETypes() is sufficient.

  • platform/MIMETypeRegistry.cpp:

(WebCore::initializeSupportedImageMIMETypes):
(WebCore::initializeSupportedJavaScriptMIMETypes):
(WebCore::initializePDFMIMETypes):
(WebCore::initializeSupportedNonImageMimeTypes):
(WebCore::initializeUnsupportedTextMIMETypes):

Move MIME type dictionary creation into initialize*MIMETypes() helpers. Additionally, remove
initializePDFAndPostScriptMIMETypes, which is no longer necessary.

(WebCore::MIMETypeRegistry::isSupportedImageMIMEType):
(WebCore::MIMETypeRegistry::isSupportedImageResourceMIMEType):
(WebCore::MIMETypeRegistry::isSupportedJavaScriptMIMEType):
(WebCore::MIMETypeRegistry::isSupportedNonImageMIMEType):
(WebCore::MIMETypeRegistry::isUnsupportedTextMIMEType):
(WebCore::MIMETypeRegistry::isPDFOrPostScriptMIMEType):

Tweak to check that the type isPDFMIMEType(), or that it's otherwise "application/postscript".

(WebCore::MIMETypeRegistry::isPDFMIMEType):
(WebCore::MIMETypeRegistry::getSupportedImageMIMETypes):
(WebCore::MIMETypeRegistry::getSupportedImageResourceMIMETypes):
(WebCore::MIMETypeRegistry::getSupportedNonImageMIMETypes):
(WebCore::MIMETypeRegistry::getPDFMIMETypes):
(WebCore::MIMETypeRegistry::getUnsupportedTextMIMETypes):

Call only the relevant MIME type initializers when needed.

(WebCore::initializePostScriptMIMETypes): Deleted.
(WebCore::initializeMIMETypeRegistry): Deleted.
(WebCore::MIMETypeRegistry::getPDFAndPostScriptMIMETypes): Deleted.

Remove an unused and unexported function.

  • platform/MIMETypeRegistry.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r223858 r223860  
     12017-10-23  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] DocumentWriter::createDocument can spend ~100ms unnecessarily converting image UTIs to MIME types
     4        https://bugs.webkit.org/show_bug.cgi?id=178618
     5        <rdar://problem/35108852>
     6
     7        Reviewed by Said Abou-Hallawa.
     8
     9        Currently, in setting up a new Document, DocumentWriter::createDocument() always asks whether or not the
     10        Document should be a PDF document by calling MIMETypeRegistry::isPDFMIMEType(), which forces lazy initialization
     11        of every MIME type dictionary (e.g. image types, PDF types, JavaScript types, etc.). As evidenced by traces,
     12        this can be an expensive operation on certain devices.
     13
     14        This patch implements two optimizations. First, we refactor the initializeSupportedImageMIMETypes() helper to
     15        stop asking for MIMETypeForImageSourceType for each of the supported UTIs. This is because the known MIME types
     16        corresponding to these hard-coded UTI types is a fixed set anyways, so we can simply iterate over a constant
     17        array of MIME types and populate the supported image (and image resource) types. Also, add assertions to ensure
     18        that we keep allowed image MIME types in sync with allowed image UTIs.
     19
     20        The second optimization removes initializeMIMETypeRegistry() altogether in favor of calling just the
     21        initialize*MIMETypes() functions needed to ensure the information required. For instance, getPDFMIMETypes()
     22        currently calls initializeMIMETypeRegistry() if the pdfMIMETypes dictionary doesn't exist, when it really only
     23        needs to ensure that the pdfMIMETypes is initialized, for which initializePDFMIMETypes() is sufficient.
     24
     25        * platform/MIMETypeRegistry.cpp:
     26        (WebCore::initializeSupportedImageMIMETypes):
     27        (WebCore::initializeSupportedJavaScriptMIMETypes):
     28        (WebCore::initializePDFMIMETypes):
     29        (WebCore::initializeSupportedNonImageMimeTypes):
     30        (WebCore::initializeUnsupportedTextMIMETypes):
     31
     32        Move MIME type dictionary creation into initialize*MIMETypes() helpers. Additionally, remove
     33        initializePDFAndPostScriptMIMETypes, which is no longer necessary.
     34
     35        (WebCore::MIMETypeRegistry::isSupportedImageMIMEType):
     36        (WebCore::MIMETypeRegistry::isSupportedImageResourceMIMEType):
     37        (WebCore::MIMETypeRegistry::isSupportedJavaScriptMIMEType):
     38        (WebCore::MIMETypeRegistry::isSupportedNonImageMIMEType):
     39        (WebCore::MIMETypeRegistry::isUnsupportedTextMIMEType):
     40        (WebCore::MIMETypeRegistry::isPDFOrPostScriptMIMEType):
     41
     42        Tweak to check that the type isPDFMIMEType(), or that it's otherwise "application/postscript".
     43
     44        (WebCore::MIMETypeRegistry::isPDFMIMEType):
     45        (WebCore::MIMETypeRegistry::getSupportedImageMIMETypes):
     46        (WebCore::MIMETypeRegistry::getSupportedImageResourceMIMETypes):
     47        (WebCore::MIMETypeRegistry::getSupportedNonImageMIMETypes):
     48        (WebCore::MIMETypeRegistry::getPDFMIMETypes):
     49        (WebCore::MIMETypeRegistry::getUnsupportedTextMIMETypes):
     50
     51        Call only the relevant MIME type initializers when needed.
     52
     53        (WebCore::initializePostScriptMIMETypes): Deleted.
     54        (WebCore::initializeMIMETypeRegistry): Deleted.
     55        (WebCore::MIMETypeRegistry::getPDFAndPostScriptMIMETypes): Deleted.
     56
     57        Remove an unused and unexported function.
     58
     59        * platform/MIMETypeRegistry.h:
     60
    1612017-10-23  Andy Estes  <aestes@apple.com>
    262
  • trunk/Source/WebCore/platform/MIMETypeRegistry.cpp

    r221778 r223860  
    3737#include "ImageSourceCG.h"
    3838#include "UTIRegistry.h"
     39#include "UTIUtilities.h"
    3940#include <wtf/RetainPtr.h>
    4041#endif
     
    6162static HashSet<String, ASCIICaseInsensitiveHash>* supportedMediaMIMETypes;
    6263static HashSet<String, ASCIICaseInsensitiveHash>* pdfMIMETypes;
    63 static HashSet<String, ASCIICaseInsensitiveHash>* pdfAndPostScriptMIMETypes;
    6464static HashSet<String, ASCIICaseInsensitiveHash>* unsupportedTextMIMETypes;
    6565
     
    6767{
    6868#if USE(CG)
    69     HashSet<String>& imageUTIs = allowedImageUTIs();
    70     for (auto& imageUTI : imageUTIs) {
    71         String mimeType = MIMETypeForImageSourceType(imageUTI);
     69    supportedImageResourceMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
     70    supportedImageMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
     71
     72    // This represents the subset of allowed image UTIs for which CoreServices has a corresponding MIME type. Keep this in sync with allowedImageUTIs().
     73    static const char* const allowedImageMIMETypes[] = { "image/tiff", "image/gif", "image/jpeg", "image/vnd.microsoft.icon", "image/jp2", "image/png", "image/bmp" };
     74    for (auto& mimeType : allowedImageMIMETypes) {
     75        supportedImageMIMETypes->add(ASCIILiteral { mimeType });
     76        supportedImageResourceMIMETypes->add(ASCIILiteral { mimeType });
     77    }
     78
     79#ifndef NDEBUG
     80    for (auto& uti : allowedImageUTIs()) {
     81        auto mimeType = MIMETypeForImageSourceType(uti);
    7282        if (!mimeType.isEmpty()) {
    73             supportedImageMIMETypes->add(mimeType);
    74             supportedImageResourceMIMETypes->add(mimeType);
     83            ASSERT(supportedImageMIMETypes->contains(mimeType));
     84            ASSERT(supportedImageResourceMIMETypes->contains(mimeType));
    7585        }
    7686    }
    7787
    78     // On Tiger and Leopard, com.microsoft.bmp doesn't have a MIME type in the registry.
    79     supportedImageMIMETypes->add("image/bmp");
    80     supportedImageResourceMIMETypes->add("image/bmp");
     88    for (auto& mime : *supportedImageMIMETypes)
     89        ASSERT_UNUSED(mime, allowedImageUTIs().contains(UTIFromMIMEType(mime)));
     90#endif
    8191
    8292    // Favicons don't have a MIME type in the registry either.
    83     supportedImageMIMETypes->add("image/vnd.microsoft.icon");
    8493    supportedImageMIMETypes->add("image/x-icon");
    85     supportedImageResourceMIMETypes->add("image/vnd.microsoft.icon");
    8694    supportedImageResourceMIMETypes->add("image/x-icon");
    8795
     
    8997    supportedImageMIMETypes->add("image/pjpeg");
    9098    supportedImageResourceMIMETypes->add("image/pjpeg");
    91 
    92     //  We don't want to try to treat all binary data as an image
    93     supportedImageMIMETypes->remove("application/octet-stream");
    94     supportedImageResourceMIMETypes->remove("application/octet-stream");
    95 
    96     //  Don't treat pdf/postscript as images directly
    97     supportedImageMIMETypes->remove("application/pdf");
    98     supportedImageMIMETypes->remove("application/postscript");
    9999
    100100#if PLATFORM(IOS)
     
    204204        "text/x-ecmascript"
    205205    };
     206
     207    supportedJavaScriptMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    206208    for (auto* type : types)
    207209        supportedJavaScriptMIMETypes->add(type);
     
    214216        "text/pdf"
    215217    };
     218
     219    pdfMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    216220    for (auto& type : types)
    217221        pdfMIMETypes->add(type);
    218 }
    219 
    220 static void initializePostScriptMIMETypes()
    221 {
    222     pdfAndPostScriptMIMETypes->add("application/postscript");
    223222}
    224223
     
    248247    };
    249248
     249    if (!supportedJavaScriptMIMETypes)
     250        initializeSupportedJavaScriptMIMETypes();
     251
     252    supportedNonImageMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash> { *supportedJavaScriptMIMETypes };
    250253    for (auto& type : types)
    251254        supportedNonImageMIMETypes->add(type);
     
    416419#endif
    417420    };
     421
     422    unsupportedTextMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    418423    for (auto& type : types)
    419424        unsupportedTextMIMETypes->add(ASCIILiteral { type });
    420 }
    421 
    422 static void initializeMIMETypeRegistry()
    423 {
    424     supportedJavaScriptMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    425     initializeSupportedJavaScriptMIMETypes();
    426 
    427     supportedNonImageMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>(*supportedJavaScriptMIMETypes);
    428     initializeSupportedNonImageMimeTypes();
    429 
    430     supportedImageResourceMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    431     supportedImageMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    432     initializeSupportedImageMIMETypes();
    433 
    434     pdfMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    435     initializePDFMIMETypes();
    436 
    437     pdfAndPostScriptMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>(*pdfMIMETypes);
    438     initializePostScriptMIMETypes();
    439 
    440     unsupportedTextMIMETypes = new HashSet<String, ASCIICaseInsensitiveHash>;
    441     initializeUnsupportedTextMIMETypes();
    442425}
    443426
     
    459442        return false;
    460443    if (!supportedImageMIMETypes)
    461         initializeMIMETypeRegistry();
     444        initializeSupportedImageMIMETypes();
    462445    return supportedImageMIMETypes->contains(getNormalizedMIMEType(mimeType));
    463446}
     
    473456        return false;
    474457    if (!supportedImageResourceMIMETypes)
    475         initializeMIMETypeRegistry();
     458        initializeSupportedImageMIMETypes();
    476459    return supportedImageResourceMIMETypes->contains(getNormalizedMIMEType(mimeType));
    477460}
     
    493476        return false;
    494477    if (!supportedJavaScriptMIMETypes)
    495         initializeMIMETypeRegistry();
     478        initializeSupportedNonImageMimeTypes();
    496479    return supportedJavaScriptMIMETypes->contains(mimeType);
    497480}
     
    538521        return false;
    539522    if (!supportedNonImageMIMETypes)
    540         initializeMIMETypeRegistry();
     523        initializeSupportedNonImageMimeTypes();
    541524    return supportedNonImageMIMETypes->contains(mimeType);
    542525}
     
    561544        return false;
    562545    if (!unsupportedTextMIMETypes)
    563         initializeMIMETypeRegistry();
     546        initializeUnsupportedTextMIMETypes();
    564547    return unsupportedTextMIMETypes->contains(mimeType);
    565548}
     
    619602bool MIMETypeRegistry::isPDFOrPostScriptMIMEType(const String& mimeType)
    620603{
    621     if (mimeType.isEmpty())
    622         return false;
    623     if (!pdfAndPostScriptMIMETypes)
    624         initializeMIMETypeRegistry();
    625     return pdfAndPostScriptMIMETypes->contains(mimeType);
     604    return isPDFMIMEType(mimeType) || mimeType == "application/postscript";
    626605}
    627606
     
    631610        return false;
    632611    if (!pdfMIMETypes)
    633         initializeMIMETypeRegistry();
     612        initializePDFMIMETypes();
    634613    return pdfMIMETypes->contains(mimeType);
    635614}
     
    652631{
    653632    if (!supportedImageMIMETypes)
    654         initializeMIMETypeRegistry();
     633        initializeSupportedImageMIMETypes();
    655634    return *supportedImageMIMETypes;
    656635}
     
    659638{
    660639    if (!supportedImageResourceMIMETypes)
    661         initializeMIMETypeRegistry();
     640        initializeSupportedImageMIMETypes();
    662641    return *supportedImageResourceMIMETypes;
    663642}
     
    673652{
    674653    if (!supportedNonImageMIMETypes)
    675         initializeMIMETypeRegistry();
     654        initializeSupportedNonImageMimeTypes();
    676655    return *supportedNonImageMIMETypes;
    677656}
     
    688667{
    689668    if (!pdfMIMETypes)
    690         initializeMIMETypeRegistry();
     669        initializePDFMIMETypes();
    691670    return *pdfMIMETypes;
    692671}
    693672
    694 HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::getPDFAndPostScriptMIMETypes()
    695 {
    696     if (!pdfAndPostScriptMIMETypes)
    697         initializeMIMETypeRegistry();
    698     return *pdfAndPostScriptMIMETypes;
    699 }
    700 
    701673HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::getUnsupportedTextMIMETypes()
    702674{
    703675    if (!unsupportedTextMIMETypes)
    704         initializeMIMETypeRegistry();
     676        initializeUnsupportedTextMIMETypes();
    705677    return *unsupportedTextMIMETypes;
    706678}
  • trunk/Source/WebCore/platform/MIMETypeRegistry.h

    r221778 r223860  
    112112    WEBCORE_EXPORT static HashSet<String, ASCIICaseInsensitiveHash>& getSupportedMediaMIMETypes();
    113113    WEBCORE_EXPORT static HashSet<String, ASCIICaseInsensitiveHash>& getPDFMIMETypes();
    114     static HashSet<String, ASCIICaseInsensitiveHash>& getPDFAndPostScriptMIMETypes();
    115114    WEBCORE_EXPORT static HashSet<String, ASCIICaseInsensitiveHash>& getUnsupportedTextMIMETypes();
    116115
Note: See TracChangeset for help on using the changeset viewer.