<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197721] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197721">197721</a></dd>
<dt>Author</dt> <dd>bfulgham@apple.com</dd>
<dt>Date</dt> <dd>2016-03-07 18:56:23 -0800 (Mon, 07 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Reduce startup and shutdown cost of resource load statistics
https://bugs.webkit.org/show_bug.cgi?id=155120
&lt;rdar://problem/25010167&gt;

Reviewed by Andy Estes.

Source/WebCore:

Move all file-related code out of WebCore.

* loader/ResourceLoadStatisticsStore.cpp:
(WebCore::ResourceLoadStatisticsStore::create): Deleted path overload.
(WebCore::ResourceLoadStatisticsStore::createEncoderFromData): Added.
(WebCore::ResourceLoadStatisticsStore::readDataFromDecoder): Added.
(WebCore::ResourceLoadStatisticsStore::ResourceLoadStatisticsStore): Deleted.
(WebCore::ResourceLoadStatisticsStore::writeDataToDisk): Deleted.
(WebCore::ResourceLoadStatisticsStore::setStatisticsStorageDirectory): Deleted.
(WebCore::ResourceLoadStatisticsStore::persistentStoragePath): Deleted.
(WebCore::ResourceLoadStatisticsStore::readDataFromDiskIfNeeded): Deleted.
(WebCore::ResourceLoadStatisticsStore::createDecoderFromDisk): Deleted.
(WebCore::ResourceLoadStatisticsStore::writeEncoderToDisk): Deleted.
* loader/ResourceLoadStatisticsStore.h:
(WebCore::ResourceLoadStatisticsStore::clear): Added.

Source/WebKit/mac:

Remove the Resource Load Statistics stuff from WK1, now that it is up and
running in WK2.

* WebView/WebView.mm:
(-[WebView _preferencesChanged:]): Remove call to read resource load
statistics from disk.
(+[WebView _applicationWillTerminate]): Remove call to write resource load
statistics to disk.

Source/WebKit2:

Use a dedicated WorkQueue to process resource load statistics data. Allow
processing to load (and save) previously stored statistics asynchronously so
that it does not delay startup.
        
Now that we have a more rational storage situation, get rid of the 'writeToDisk'
method since it is no longer needed in the WK2 layer.

Move all of the Resource Load Statistics file handling code from WebCore to this
API layer.

* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore): Initialize
member variable with storage path, rather than passing to WebCore code.
(WebKit::WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated): Revised to
use the new WorkQueue code.
(WebKit::WebResourceLoadStatisticsStore::setResourceLoadStatisticsEnabled): When
activating the feature, purge any old statistics before loading from disk.
(WebKit::WebResourceLoadStatisticsStore::readDataFromDiskIfNeeded): Added.
(WebKit::WebResourceLoadStatisticsStore::processWillOpenConnection): Added.
(WebKit::WebResourceLoadStatisticsStore::processDidCloseConnection): Added.
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate): Make sure all
of the WorkQueue tasks are done before terminating.
(WebKit::WebResourceLoadStatisticsStore::persistentStoragePath): Moved from WebCore.
(WebKit::WebResourceLoadStatisticsStore::writeEncoderToDisk): Ditto.
(WebKit::WebResourceLoadStatisticsStore::createDecoderFromDisk): Ditto.
(WebKit::WebResourceLoadStatisticsStore::writeToDisk): Deleted.
* UIProcess/WebResourceLoadStatisticsStore.h:
(WebKit::WebResourceLoadStatisticsStore::coreStore):
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::WebsiteDataStore::webProcessWillOpenConnection): Call new WebResourceLoadStatisticsStore code.
(WebKit::WebsiteDataStore::webProcessDidCloseConnection): Ditto.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadObservercpp">trunk/Source/WebCore/loader/ResourceLoadObserver.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadStatisticsStorecpp">trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceLoadStatisticsStoreh">trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewmm">trunk/Source/WebKit/mac/WebView/WebView.mm</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebResourceLoadStatisticsStorecpp">trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebResourceLoadStatisticsStoreh">trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebsiteDataWebsiteDataStorecpp">trunk/Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebCore/ChangeLog        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2016-03-07  Brent Fulgham  &lt;bfulgham@apple.com&gt;
+
+        Reduce startup and shutdown cost of resource load statistics
+        https://bugs.webkit.org/show_bug.cgi?id=155120
+        &lt;rdar://problem/25010167&gt;
+
+        Reviewed by Andy Estes.
+
+        Move all file-related code out of WebCore.
+
+        * loader/ResourceLoadStatisticsStore.cpp:
+        (WebCore::ResourceLoadStatisticsStore::create): Deleted path overload.
+        (WebCore::ResourceLoadStatisticsStore::createEncoderFromData): Added.
+        (WebCore::ResourceLoadStatisticsStore::readDataFromDecoder): Added.
+        (WebCore::ResourceLoadStatisticsStore::ResourceLoadStatisticsStore): Deleted.
+        (WebCore::ResourceLoadStatisticsStore::writeDataToDisk): Deleted.
+        (WebCore::ResourceLoadStatisticsStore::setStatisticsStorageDirectory): Deleted.
+        (WebCore::ResourceLoadStatisticsStore::persistentStoragePath): Deleted.
+        (WebCore::ResourceLoadStatisticsStore::readDataFromDiskIfNeeded): Deleted.
+        (WebCore::ResourceLoadStatisticsStore::createDecoderFromDisk): Deleted.
+        (WebCore::ResourceLoadStatisticsStore::writeEncoderToDisk): Deleted.
+        * loader/ResourceLoadStatisticsStore.h:
+        (WebCore::ResourceLoadStatisticsStore::clear): Added.
+
</ins><span class="cx"> 2016-03-07  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash in WebCore::RenderElement::containingBlockForObjectInFlow
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadObservercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/ResourceLoadObserver.cpp (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadObserver.cpp        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebCore/loader/ResourceLoadObserver.cpp        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -62,6 +62,9 @@
</span><span class="cx">     if (!Settings::resourceLoadStatisticsEnabled())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (!m_store)
+        return;
+
</ins><span class="cx">     ASSERT(frame.document());
</span><span class="cx">     ASSERT(topFrame.document());
</span><span class="cx">     ASSERT(topFrame.page());
</span><span class="lines">@@ -148,6 +151,9 @@
</span><span class="cx">     if (!Settings::resourceLoadStatisticsEnabled())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (!m_store)
+        return;
+
</ins><span class="cx">     bool needPrivacy = (frame &amp;&amp; frame-&gt;page()) ? frame-&gt;page()-&gt;usesEphemeralSession() : false;
</span><span class="cx">     if (needPrivacy)
</span><span class="cx">         return;
</span><span class="lines">@@ -208,6 +214,9 @@
</span><span class="cx">     if (!Settings::resourceLoadStatisticsEnabled())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (!m_store)
+        return;
+
</ins><span class="cx">     bool needPrivacy = document.page() ? document.page()-&gt;usesEphemeralSession() : false;
</span><span class="cx">     if (needPrivacy)
</span><span class="cx">         return;
</span><span class="lines">@@ -261,7 +270,7 @@
</span><span class="cx"> 
</span><span class="cx"> String ResourceLoadObserver::statisticsForOrigin(const String&amp; origin)
</span><span class="cx"> {
</span><del>-    return m_store-&gt;statisticsForOrigin(origin);
</del><ins>+    return m_store ? m_store-&gt;statisticsForOrigin(origin) : emptyString();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadStatisticsStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -41,21 +41,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-Ref&lt;ResourceLoadStatisticsStore&gt; ResourceLoadStatisticsStore::create(const String&amp; resourceLoadStatisticsDirectory)
-{
-    return adoptRef(*new ResourceLoadStatisticsStore(resourceLoadStatisticsDirectory));
-}
-
</del><span class="cx"> Ref&lt;ResourceLoadStatisticsStore&gt; ResourceLoadStatisticsStore::create()
</span><span class="cx"> {
</span><span class="cx">     return adoptRef(*new ResourceLoadStatisticsStore());
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-ResourceLoadStatisticsStore::ResourceLoadStatisticsStore(const String&amp; resourceLoadStatisticsDirectory)
-    : m_storagePath(resourceLoadStatisticsDirectory)
-{
-}
-    
</del><span class="cx"> bool ResourceLoadStatisticsStore::isPrevalentResource(const String&amp; primaryDomain) const
</span><span class="cx"> {
</span><span class="cx">     auto mapEntry = m_resourceStatisticsMap.find(primaryDomain);
</span><span class="lines">@@ -76,43 +66,24 @@
</span><span class="cx"> 
</span><span class="cx"> typedef HashMap&lt;String, ResourceLoadStatistics&gt;::KeyValuePairType StatisticsValue;
</span><span class="cx"> 
</span><del>-void ResourceLoadStatisticsStore::writeDataToDisk()
</del><ins>+std::unique_ptr&lt;KeyedEncoder&gt; ResourceLoadStatisticsStore::createEncoderFromData()
</ins><span class="cx"> {
</span><span class="cx">     auto encoder = KeyedEncoder::encoder();
</span><span class="cx">     
</span><span class="cx">     encoder-&gt;encodeObjects(&quot;browsingStatistics&quot;, m_resourceStatisticsMap.begin(), m_resourceStatisticsMap.end(), [this](KeyedEncoder&amp; encoderInner, const StatisticsValue&amp; origin) {
</span><span class="cx">         origin.value.encode(encoderInner);
</span><span class="cx">     });
</span><del>-    
-    writeEncoderToDisk(*encoder.get(), &quot;full_browsing_session&quot;);
-}
</del><span class="cx"> 
</span><del>-void ResourceLoadStatisticsStore::setStatisticsStorageDirectory(const String&amp; path)
-{
-    m_storagePath = path;
-    readDataFromDiskIfNeeded();
</del><ins>+    return encoder;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-String ResourceLoadStatisticsStore::persistentStoragePath(const String&amp; label) const
</del><ins>+void ResourceLoadStatisticsStore::readDataFromDecoder(KeyedDecoder&amp; decoder)
</ins><span class="cx"> {
</span><del>-    if (m_storagePath.isEmpty())
-        return emptyString();
-
-    // TODO Decide what to call this file
-    return pathByAppendingComponent(m_storagePath, label + &quot;_resourceLog.plist&quot;);
-}
-
-void ResourceLoadStatisticsStore::readDataFromDiskIfNeeded()
-{
</del><span class="cx">     if (m_resourceStatisticsMap.size())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    auto decoder = createDecoderFromDisk(&quot;full_browsing_session&quot;);
-    if (!decoder)
-        return;
-
</del><span class="cx">     Vector&lt;ResourceLoadStatistics&gt; loadedStatistics;
</span><del>-    bool succeeded = decoder-&gt;decodeObjects(&quot;browsingStatistics&quot;, loadedStatistics, [this](KeyedDecoder&amp; decoderInner, ResourceLoadStatistics&amp; statistics) {
</del><ins>+    bool succeeded = decoder.decodeObjects(&quot;browsingStatistics&quot;, loadedStatistics, [this](KeyedDecoder&amp; decoderInner, ResourceLoadStatistics&amp; statistics) {
</ins><span class="cx">         return statistics.decode(decoderInner);
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="lines">@@ -123,48 +94,6 @@
</span><span class="cx">         m_resourceStatisticsMap.set(statistics.highLevelDomain, statistics);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;KeyedDecoder&gt; ResourceLoadStatisticsStore::createDecoderFromDisk(const String&amp; label) const
-{
-    String resourceLog = persistentStoragePath(label);
-    if (resourceLog.isEmpty())
-        return nullptr;
-    
-    RefPtr&lt;SharedBuffer&gt; rawData = SharedBuffer::createWithContentsOfFile(resourceLog);
-    if (!rawData)
-        return nullptr;
-    
-    return KeyedDecoder::decoder(reinterpret_cast&lt;const uint8_t*&gt;(rawData-&gt;data()), rawData-&gt;size());
-}
-    
-void ResourceLoadStatisticsStore::writeEncoderToDisk(KeyedEncoder&amp; encoder, const String&amp; label) const
-{
-#if LOG_STATISTICS_TO_FILE
-    RefPtr&lt;SharedBuffer&gt; rawData = encoder.finishEncoding();
-    if (!rawData)
-        return;
-    
-    String resourceLog = persistentStoragePath(label);
-    if (resourceLog.isEmpty())
-        return;
-
-    if (!m_storagePath.isEmpty())
-        makeAllDirectories(m_storagePath);
-
-    auto handle = openFile(resourceLog, OpenForWrite);
-    if (!handle)
-        return;
-    
-    int64_t writtenBytes = writeToFile(handle, rawData-&gt;data(), rawData-&gt;size());
-    closeFile(handle);
-    
-    if (writtenBytes != static_cast&lt;int64_t&gt;(rawData-&gt;size()))
-        WTFLogAlways(&quot;ResourceLoadStatistics: We only wrote %lld out of %d bytes to disk&quot;, writtenBytes, rawData-&gt;size());
-#else
-    UNUSED_PARAM(encoder);
-    UNUSED_PARAM(label);
-#endif
-}
-
</del><span class="cx"> String ResourceLoadStatisticsStore::statisticsForOrigin(const String&amp; origin)
</span><span class="cx"> {
</span><span class="cx">     auto iter = m_resourceStatisticsMap.find(origin);
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceLoadStatisticsStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -38,17 +38,16 @@
</span><span class="cx"> 
</span><span class="cx"> class ResourceLoadStatisticsStore : public RefCounted&lt;ResourceLoadStatisticsStore&gt; {
</span><span class="cx"> public:
</span><del>-    WEBCORE_EXPORT static Ref&lt;ResourceLoadStatisticsStore&gt; create(const String&amp; resourceLoadStatisticsDirectory);
</del><span class="cx">     WEBCORE_EXPORT static Ref&lt;ResourceLoadStatisticsStore&gt; create();
</span><span class="cx"> 
</span><del>-    WEBCORE_EXPORT void writeDataToDisk();
-    WEBCORE_EXPORT void readDataFromDiskIfNeeded();
-    WEBCORE_EXPORT void setStatisticsStorageDirectory(const String&amp;);
</del><ins>+    WEBCORE_EXPORT std::unique_ptr&lt;KeyedEncoder&gt; createEncoderFromData();
+    WEBCORE_EXPORT void readDataFromDecoder(KeyedDecoder&amp;);
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT String statisticsForOrigin(const String&amp;);
</span><span class="cx"> 
</span><span class="cx">     bool isEmpty() const { return m_resourceStatisticsMap.isEmpty(); }
</span><span class="cx">     size_t size() const { return m_resourceStatisticsMap.size(); }
</span><ins>+    void clear() { m_resourceStatisticsMap.clear(); }
</ins><span class="cx"> 
</span><span class="cx">     ResourceLoadStatistics&amp; resourceStatisticsForPrimaryDomain(const String&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -63,14 +62,8 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ResourceLoadStatisticsStore() = default;
</span><del>-    ResourceLoadStatisticsStore(const String&amp; resourceLoadStatisticsDirectory);
-    String persistentStoragePath(const String&amp; label) const;
</del><span class="cx"> 
</span><del>-    std::unique_ptr&lt;KeyedDecoder&gt; createDecoderFromDisk(const String&amp; label) const;
-    void writeEncoderToDisk(KeyedEncoder&amp;, const String&amp; label) const;
-
</del><span class="cx">     HashMap&lt;String, ResourceLoadStatistics&gt; m_resourceStatisticsMap;
</span><del>-    String m_storagePath;
</del><span class="cx">     std::function&lt;void()&gt; m_dataAddedHandler;
</span><span class="cx"> };
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebKit/mac/ChangeLog        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2016-03-07  Brent Fulgham  &lt;bfulgham@apple.com&gt;
+
+        Reduce startup and shutdown cost of resource load statistics
+        https://bugs.webkit.org/show_bug.cgi?id=155120
+        &lt;rdar://problem/25010167&gt;
+
+        Reviewed by Andy Estes.
+
+        Remove the Resource Load Statistics stuff from WK1, now that it is up and
+        running in WK2.
+
+        * WebView/WebView.mm:
+        (-[WebView _preferencesChanged:]): Remove call to read resource load
+        statistics from disk.
+        (+[WebView _applicationWillTerminate]): Remove call to write resource load
+        statistics to disk.
+
</ins><span class="cx"> 2016-03-06  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Reduce page cache capacity from 3 to 2.
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebView.mm        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -759,15 +759,7 @@
</span><span class="cx">     if (initialized)
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    NSString *appName = [[NSBundle mainBundle] bundleIdentifier];
-    if (!appName)
-        appName = [[NSProcessInfo processInfo] processName];
-    
-    ASSERT(appName);
-    
-    NSString *supportDirectory = [NSString _webkit_localStorageDirectoryWithBundleIdentifier:appName];
-
-    resourceLoadStatisticsStore = &amp;WebCore::ResourceLoadStatisticsStore::create(supportDirectory).leakRef();
</del><ins>+    resourceLoadStatisticsStore = &amp;WebCore::ResourceLoadStatisticsStore::create().leakRef();
</ins><span class="cx">     ResourceLoadObserver::sharedObserver().setStatisticsStore(*resourceLoadStatisticsStore);
</span><span class="cx">     
</span><span class="cx">     initialized = YES;
</span><span class="lines">@@ -2480,8 +2472,6 @@
</span><span class="cx">     settings.setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]);
</span><span class="cx"> 
</span><span class="cx">     settings.setResourceLoadStatisticsEnabled([preferences resourceLoadStatisticsEnabled]);
</span><del>-    if (resourceLoadStatisticsStore)
-        resourceLoadStatisticsStore-&gt;readDataFromDiskIfNeeded();
</del><span class="cx"> 
</span><span class="cx"> #if ENABLE(GAMEPAD)
</span><span class="cx">     RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled([preferences gamepadsEnabled]);
</span><span class="lines">@@ -4851,9 +4841,6 @@
</span><span class="cx"> {   
</span><span class="cx">     applicationIsTerminating = YES;
</span><span class="cx"> 
</span><del>-    if (resourceLoadStatisticsStore)
-        resourceLoadStatisticsStore-&gt;writeDataToDisk();
-
</del><span class="cx">     if (fastDocumentTeardownEnabled())
</span><span class="cx">         [self closeAllWebViews];
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebKit2/ChangeLog        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2016-03-07  Brent Fulgham  &lt;bfulgham@apple.com&gt;
+
+        Reduce startup and shutdown cost of resource load statistics
+        https://bugs.webkit.org/show_bug.cgi?id=155120
+        &lt;rdar://problem/25010167&gt;
+
+        Reviewed by Andy Estes.
+
+        Use a dedicated WorkQueue to process resource load statistics data. Allow
+        processing to load (and save) previously stored statistics asynchronously so
+        that it does not delay startup.
+        
+        Now that we have a more rational storage situation, get rid of the 'writeToDisk'
+        method since it is no longer needed in the WK2 layer.
+
+        Move all of the Resource Load Statistics file handling code from WebCore to this
+        API layer.
+
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore): Initialize
+        member variable with storage path, rather than passing to WebCore code.
+        (WebKit::WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated): Revised to
+        use the new WorkQueue code.
+        (WebKit::WebResourceLoadStatisticsStore::setResourceLoadStatisticsEnabled): When
+        activating the feature, purge any old statistics before loading from disk.
+        (WebKit::WebResourceLoadStatisticsStore::readDataFromDiskIfNeeded): Added.
+        (WebKit::WebResourceLoadStatisticsStore::processWillOpenConnection): Added.
+        (WebKit::WebResourceLoadStatisticsStore::processDidCloseConnection): Added.
+        (WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate): Make sure all
+        of the WorkQueue tasks are done before terminating.
+        (WebKit::WebResourceLoadStatisticsStore::persistentStoragePath): Moved from WebCore.
+        (WebKit::WebResourceLoadStatisticsStore::writeEncoderToDisk): Ditto.
+        (WebKit::WebResourceLoadStatisticsStore::createDecoderFromDisk): Ditto.
+        (WebKit::WebResourceLoadStatisticsStore::writeToDisk): Deleted.
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+        (WebKit::WebResourceLoadStatisticsStore::coreStore):
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::WebsiteDataStore::webProcessWillOpenConnection): Call new WebResourceLoadStatisticsStore code.
+        (WebKit::WebsiteDataStore::webProcessDidCloseConnection): Ditto.
+
</ins><span class="cx"> 2016-03-07  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix cookies with private browsing and NetworkSession
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebResourceLoadStatisticsStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -29,7 +29,9 @@
</span><span class="cx"> #include &quot;WebProcessMessages.h&quot;
</span><span class="cx"> #include &quot;WebProcessPool.h&quot;
</span><span class="cx"> #include &quot;WebResourceLoadStatisticsStoreMessages.h&quot;
</span><ins>+#include &lt;WebCore/KeyedCoding.h&gt;
</ins><span class="cx"> #include &lt;WebCore/ResourceLoadStatisticsStore.h&gt;
</span><ins>+#include &lt;wtf/threads/BinarySemaphore.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="lines">@@ -41,7 +43,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String&amp; resourceLoadStatisticsDirectory)
</span><del>-    : m_resourceStatisticsStore(WebCore::ResourceLoadStatisticsStore::create(resourceLoadStatisticsDirectory))
</del><ins>+    : m_resourceStatisticsStore(WebCore::ResourceLoadStatisticsStore::create())
+    , m_statisticsQueue(WorkQueue::create(&quot;WebResourceLoadStatisticsStore Process Data Queue&quot;))
+    , m_storagePath(resourceLoadStatisticsDirectory)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -52,6 +56,11 @@
</span><span class="cx"> void WebResourceLoadStatisticsStore::resourceLoadStatisticsUpdated(const Vector&lt;WebCore::ResourceLoadStatistics&gt;&amp; origins)
</span><span class="cx"> {
</span><span class="cx">     coreStore().mergeStatistics(origins);
</span><ins>+    // TODO: Analyze statistics to recognize prevalent domains. &lt;rdar://problem/24913272&gt;
+    // TODO: Notify individual WebProcesses of prevalent domains. &lt;rdar://problem/24703099&gt;
+    auto encoder = coreStore().createEncoderFromData();
+    
+    writeEncoderToDisk(*encoder.get(), &quot;full_browsing_session&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebResourceLoadStatisticsStore::setResourceLoadStatisticsEnabled(bool enabled)
</span><span class="lines">@@ -74,24 +83,82 @@
</span><span class="cx">     if (!m_resourceLoadStatisticsEnabled)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    coreStore().readDataFromDiskIfNeeded();
</del><ins>+    RefPtr&lt;WebResourceLoadStatisticsStore&gt; self(this);
+    m_statisticsQueue-&gt;dispatch([self] {
+        self-&gt;coreStore().clear();
+
+        auto decoder = self-&gt;createDecoderFromDisk(&quot;full_browsing_session&quot;);
+        if (!decoder)
+            return;
+
+        self-&gt;coreStore().readDataFromDecoder(*decoder);
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebResourceLoadStatisticsStore::writeToDisk()
</del><ins>+void WebResourceLoadStatisticsStore::processWillOpenConnection(WebProcessProxy&amp;, IPC::Connection&amp; connection)
</ins><span class="cx"> {
</span><del>-    if (!m_resourceLoadStatisticsEnabled)
-        return;
-    
-    coreStore().writeDataToDisk();
</del><ins>+    connection.addWorkQueueMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName(), &amp;m_statisticsQueue.get(), this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebResourceLoadStatisticsStore::processDidCloseConnection(WebProcessProxy&amp;, IPC::Connection&amp; connection)
+{
+    connection.removeWorkQueueMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName());
+}
+
</ins><span class="cx"> void WebResourceLoadStatisticsStore::applicationWillTerminate()
</span><span class="cx"> {
</span><del>-    if (!m_resourceLoadStatisticsEnabled)
</del><ins>+    BinarySemaphore semaphore;
+    m_statisticsQueue-&gt;dispatch([this, &amp;semaphore] {
+        // Make sure any ongoing work in our queue is finished before we terminate.
+        semaphore.signal();
+    });
+    semaphore.wait(std::numeric_limits&lt;double&gt;::max());
+}
+
+String WebResourceLoadStatisticsStore::persistentStoragePath(const String&amp; label) const
+{
+    if (m_storagePath.isEmpty())
+        return emptyString();
+    
+    // TODO Decide what to call this file
+    return pathByAppendingComponent(m_storagePath, label + &quot;_resourceLog.plist&quot;);
+}
+
+void WebResourceLoadStatisticsStore::writeEncoderToDisk(KeyedEncoder&amp; encoder, const String&amp; label) const
+{
+    RefPtr&lt;SharedBuffer&gt; rawData = encoder.finishEncoding();
+    if (!rawData)
</ins><span class="cx">         return;
</span><ins>+    
+    String resourceLog = persistentStoragePath(label);
+    if (resourceLog.isEmpty())
+        return;
+    
+    if (!m_storagePath.isEmpty())
+        makeAllDirectories(m_storagePath);
+    
+    auto handle = openFile(resourceLog, OpenForWrite);
+    if (!handle)
+        return;
+    
+    int64_t writtenBytes = writeToFile(handle, rawData-&gt;data(), rawData-&gt;size());
+    closeFile(handle);
+    
+    if (writtenBytes != static_cast&lt;int64_t&gt;(rawData-&gt;size()))
+        WTFLogAlways(&quot;WebResourceLoadStatisticsStore: We only wrote %d out of %d bytes to disk&quot;, static_cast&lt;unsigned&gt;(writtenBytes), rawData-&gt;size());
+}
</ins><span class="cx"> 
</span><del>-    // FIXME(154642): TEMPORARY CODE: This should not be done in one long operation when exiting.
-    writeToDisk();
</del><ins>+std::unique_ptr&lt;KeyedDecoder&gt; WebResourceLoadStatisticsStore::createDecoderFromDisk(const String&amp; label) const
+{
+    String resourceLog = persistentStoragePath(label);
+    if (resourceLog.isEmpty())
+        return nullptr;
+    
+    RefPtr&lt;SharedBuffer&gt; rawData = SharedBuffer::createWithContentsOfFile(resourceLog);
+    if (!rawData)
+        return nullptr;
+    
+    return KeyedDecoder::decoder(reinterpret_cast&lt;const uint8_t*&gt;(rawData-&gt;data()), rawData-&gt;size());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebResourceLoadStatisticsStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -33,13 +33,20 @@
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><ins>+namespace WTF {
+class WorkQueue;
+}
+
</ins><span class="cx"> namespace WebCore {
</span><ins>+class KeyedDecoder;
+class KeyedEncoder;
</ins><span class="cx"> struct ResourceLoadStatistics;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> class WebProcessPool;
</span><ins>+class WebProcessProxy;
</ins><span class="cx"> 
</span><span class="cx"> class WebResourceLoadStatisticsStore : public IPC::Connection::WorkQueueMessageReceiver {
</span><span class="cx"> public:
</span><span class="lines">@@ -51,22 +58,31 @@
</span><span class="cx">     
</span><span class="cx">     void resourceLoadStatisticsUpdated(const Vector&lt;WebCore::ResourceLoadStatistics&gt;&amp; origins);
</span><span class="cx"> 
</span><ins>+    void processWillOpenConnection(WebProcessProxy&amp;, IPC::Connection&amp;);
+    void processDidCloseConnection(WebProcessProxy&amp;, IPC::Connection&amp;);
</ins><span class="cx">     void applicationWillTerminate();
</span><span class="cx"> 
</span><del>-    void writeToDisk();
</del><span class="cx">     void readDataFromDiskIfNeeded();
</span><span class="cx"> 
</span><span class="cx">     void mergeStatistics(const Vector&lt;WebCore::ResourceLoadStatistics&gt;&amp;);
</span><span class="cx"> 
</span><span class="cx">     WebCore::ResourceLoadStatisticsStore&amp; coreStore() { return m_resourceStatisticsStore.get(); }
</span><del>-    
</del><ins>+    const WebCore::ResourceLoadStatisticsStore&amp; coreStore() const { return m_resourceStatisticsStore.get(); }
+
</ins><span class="cx"> private:
</span><span class="cx">     explicit WebResourceLoadStatisticsStore(const String&amp;);
</span><del>-    
</del><ins>+
+    String persistentStoragePath(const String&amp; label) const;
+
</ins><span class="cx">     // IPC::MessageReceiver
</span><span class="cx">     void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;) override;
</span><del>-    
</del><ins>+
+    void writeEncoderToDisk(WebCore::KeyedEncoder&amp;, const String&amp; label) const;
+    std::unique_ptr&lt;WebCore::KeyedDecoder&gt; createDecoderFromDisk(const String&amp; label) const;
+
</ins><span class="cx">     Ref&lt;WebCore::ResourceLoadStatisticsStore&gt; m_resourceStatisticsStore;
</span><ins>+    Ref&lt;WTF::WorkQueue&gt; m_statisticsQueue;
+    String m_storagePath;
</ins><span class="cx">     bool m_resourceLoadStatisticsEnabled { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebsiteDataWebsiteDataStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.cpp (197720 => 197721)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.cpp        2016-03-08 02:40:12 UTC (rev 197720)
+++ trunk/Source/WebKit2/UIProcess/WebsiteData/WebsiteDataStore.cpp        2016-03-08 02:56:23 UTC (rev 197721)
</span><span class="lines">@@ -981,7 +981,8 @@
</span><span class="cx">     if (m_storageManager)
</span><span class="cx">         m_storageManager-&gt;processWillOpenConnection(webProcessProxy, connection);
</span><span class="cx"> 
</span><del>-    connection.addWorkQueueMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName(), &amp;m_queue.get(), m_resourceLoadStatistics.get());
</del><ins>+    if (m_resourceLoadStatistics)
+        m_resourceLoadStatistics-&gt;processWillOpenConnection(webProcessProxy, connection);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebsiteDataStore::webPageWillOpenConnection(WebPageProxy&amp; webPageProxy, IPC::Connection&amp; connection)
</span><span class="lines">@@ -998,7 +999,8 @@
</span><span class="cx"> 
</span><span class="cx"> void WebsiteDataStore::webProcessDidCloseConnection(WebProcessProxy&amp; webProcessProxy, IPC::Connection&amp; connection)
</span><span class="cx"> {
</span><del>-    connection.removeWorkQueueMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName());
</del><ins>+    if (m_resourceLoadStatistics)
+        m_resourceLoadStatistics-&gt;processDidCloseConnection(webProcessProxy, connection);
</ins><span class="cx"> 
</span><span class="cx">     if (m_storageManager)
</span><span class="cx">         m_storageManager-&gt;processDidCloseConnection(webProcessProxy, connection);
</span></span></pre>
</div>
</div>

</body>
</html>