<!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>[198620] trunk/Source/WebInspectorUI</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/198620">198620</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-24 01:10:01 -0700 (Thu, 24 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Miscellaneous performance fixes in Timeline recording
https://bugs.webkit.org/show_bug.cgi?id=155832

Patch by Joseph Pecoraro &lt;pecoraro@apple.com&gt; on 2016-03-24
Reviewed by Timothy Hatcher.

* UserInterface/Models/CallingContextTree.js:
(WebInspector.CCTNode.prototype.hasChildren):
No need to allocate an array with all of the properties, we can just
check if there is at least one property using a short circuit for..in.
Performance was always faster for empty, small, and large objects
in micro benchmarks.

* UserInterface/Views/DataGrid.js:
(WebInspector.DataGrid.prototype.layout):
Avoid causing DOM layout when positioning resizers. They only need
a layout if we are resizing the DataGrid, or the initial layout.

* UserInterface/Views/NavigationBar.js:
(WebInspector.NavigationBar):
(WebInspector.NavigationBar.prototype.needsLayout):
(WebInspector.NavigationBar.prototype.layout):
Avoid causing DOM layout every View layout. In fact, only do a
DOM layout when someone has triggered a needsLayout on this
navigation bar. A basic dirty layout (triggered by a parent)
should not have caused us to resize.

* UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js:
* UserInterface/Views/LayoutTimelineOverviewGraph.js:
(WebInspector.LayoutTimelineOverviewGraph.prototype.layout):
* UserInterface/Views/MemoryTimelineOverviewGraph.js:
(WebInspector.MemoryTimelineOverviewGraph.prototype.reset):
(WebInspector.MemoryTimelineOverviewGraph.prototype._updateLegend):
* UserInterface/Views/NetworkTimelineOverviewGraph.js:
* UserInterface/Views/RenderingFrameTimelineOverviewGraph.js:
(WebInspector.RenderingFrameTimelineOverviewGraph.prototype.layout):
* UserInterface/Views/ScriptTimelineOverviewGraph.js:
Avoid doing any work in non-visible graphs. This was very common
because the RenderingFrameTimelineOverviewGraph is never visible
when the other timeline graphs are, but was performing lots of work.

* UserInterface/Views/MemoryCategoryView.js:
(WebInspector.MemoryCategoryView.prototype.clear):
(WebInspector.MemoryCategoryView.prototype._updateDetails):
(WebInspector.MemoryCategoryView):
* UserInterface/Views/MemoryTimelineView.js:
(WebInspector.MemoryTimelineView.prototype.reset):
(WebInspector.MemoryTimelineView.prototype._updateUsageLegend):
(WebInspector.MemoryTimelineView.prototype._updateMaxComparisonLegend):
Cache values to avoid textContent calls even if the content did not change.
This reduces unnecessary work when the values wouldn't change.

* UserInterface/Views/TimelineRecordBar.js:
(WebInspector.TimelineRecordBar.createCombinedBars):
(WebInspector.TimelineRecordBar.prototype.set records):
Revert to fast loop and as this code path is very hot and for..of iteration
was showing up in profiles. Remove assert which seems rather pointless but
showed up in profiles.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsCallingContextTreejs">trunk/Source/WebInspectorUI/UserInterface/Models/CallingContextTree.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs">trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsLayoutTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsMemoryCategoryViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/MemoryCategoryView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsMemoryTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsMemoryTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNavigationBarjs">trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsRenderingFrameTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsScriptTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineRecordBarjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -1,3 +1,63 @@
</span><ins>+2016-03-24  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Miscellaneous performance fixes in Timeline recording
+        https://bugs.webkit.org/show_bug.cgi?id=155832
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Models/CallingContextTree.js:
+        (WebInspector.CCTNode.prototype.hasChildren):
+        No need to allocate an array with all of the properties, we can just
+        check if there is at least one property using a short circuit for..in.
+        Performance was always faster for empty, small, and large objects
+        in micro benchmarks.
+
+        * UserInterface/Views/DataGrid.js:
+        (WebInspector.DataGrid.prototype.layout):
+        Avoid causing DOM layout when positioning resizers. They only need
+        a layout if we are resizing the DataGrid, or the initial layout.
+
+        * UserInterface/Views/NavigationBar.js:
+        (WebInspector.NavigationBar):
+        (WebInspector.NavigationBar.prototype.needsLayout):
+        (WebInspector.NavigationBar.prototype.layout):
+        Avoid causing DOM layout every View layout. In fact, only do a
+        DOM layout when someone has triggered a needsLayout on this
+        navigation bar. A basic dirty layout (triggered by a parent)
+        should not have caused us to resize.
+
+        * UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js:
+        * UserInterface/Views/LayoutTimelineOverviewGraph.js:
+        (WebInspector.LayoutTimelineOverviewGraph.prototype.layout):
+        * UserInterface/Views/MemoryTimelineOverviewGraph.js:
+        (WebInspector.MemoryTimelineOverviewGraph.prototype.reset):
+        (WebInspector.MemoryTimelineOverviewGraph.prototype._updateLegend):
+        * UserInterface/Views/NetworkTimelineOverviewGraph.js:
+        * UserInterface/Views/RenderingFrameTimelineOverviewGraph.js:
+        (WebInspector.RenderingFrameTimelineOverviewGraph.prototype.layout):
+        * UserInterface/Views/ScriptTimelineOverviewGraph.js:
+        Avoid doing any work in non-visible graphs. This was very common
+        because the RenderingFrameTimelineOverviewGraph is never visible
+        when the other timeline graphs are, but was performing lots of work.
+
+        * UserInterface/Views/MemoryCategoryView.js:
+        (WebInspector.MemoryCategoryView.prototype.clear):
+        (WebInspector.MemoryCategoryView.prototype._updateDetails):
+        (WebInspector.MemoryCategoryView):
+        * UserInterface/Views/MemoryTimelineView.js:
+        (WebInspector.MemoryTimelineView.prototype.reset):
+        (WebInspector.MemoryTimelineView.prototype._updateUsageLegend):
+        (WebInspector.MemoryTimelineView.prototype._updateMaxComparisonLegend):
+        Cache values to avoid textContent calls even if the content did not change.
+        This reduces unnecessary work when the values wouldn't change.
+
+        * UserInterface/Views/TimelineRecordBar.js:
+        (WebInspector.TimelineRecordBar.createCombinedBars):
+        (WebInspector.TimelineRecordBar.prototype.set records):
+        Revert to fast loop and as this code path is very hot and for..of iteration
+        was showing up in profiles. Remove assert which seems rather pointless but
+        showed up in profiles.
+
</ins><span class="cx"> 2016-03-24  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Large repaints while typing in the console tab
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsCallingContextTreejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/CallingContextTree.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/CallingContextTree.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/CallingContextTree.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -244,7 +244,7 @@
</span><span class="cx"> 
</span><span class="cx">     hasChildren()
</span><span class="cx">     {
</span><del>-        return !!Object.getOwnPropertyNames(this._children).length;
</del><ins>+        return !isEmptyObject(this._children);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     findOrMakeChild(stackFrame)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -593,8 +593,10 @@
</span><span class="cx">     //
</span><span class="cx">     // If this function is not called after the DataGrid is attached to its
</span><span class="cx">     // parent element, then the DataGrid's columns will not be resizable.
</span><del>-    layout()
</del><ins>+    layout(layoutReason)
</ins><span class="cx">     {
</span><ins>+        let firstUpdate = false;
+
</ins><span class="cx">         // Do not attempt to use offsets if we're not attached to the document tree yet.
</span><span class="cx">         if (!this._columnWidthsInitialized &amp;&amp; this.element.offsetWidth) {
</span><span class="cx">             // Give all the columns initial widths now so that during a resize,
</span><span class="lines">@@ -618,10 +620,13 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             this._columnWidthsInitialized = true;
</span><ins>+            firstUpdate = true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        this._positionResizerElements();
-        this._positionHeaderViews();
</del><ins>+        if (layoutReason == WebInspector.View.LayoutReason.Resize || firstUpdate) {
+            this._positionResizerElements();
+            this._positionHeaderViews();
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     columnWidthsMap()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineOverviewGraph.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -48,6 +48,9 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><ins>+        if (!this.visible)
+            return;
+
</ins><span class="cx">         this.element.removeChildren();
</span><span class="cx"> 
</span><span class="cx">         // This may display records past the current time marker.
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsLayoutTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineOverviewGraph.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineOverviewGraph.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineOverviewGraph.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -61,6 +61,9 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><ins>+        if (!this.visible)
+            return;
+
</ins><span class="cx">         this._updateRowLayout(this._timelinePaintRecordRow);
</span><span class="cx">         this._updateRowLayout(this._timelineLayoutRecordRow);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsMemoryCategoryViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/MemoryCategoryView.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/MemoryCategoryView.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/MemoryCategoryView.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -64,6 +64,9 @@
</span><span class="cx"> 
</span><span class="cx">     clear()
</span><span class="cx">     {
</span><ins>+        this._cachedMinSize = undefined;
+        this._cachedMaxSize = undefined;
+
</ins><span class="cx">         this._chart.clear();
</span><span class="cx">         this._chart.needsLayout();
</span><span class="cx">     }
</span><span class="lines">@@ -109,6 +112,12 @@
</span><span class="cx"> 
</span><span class="cx">     _updateDetails(minSize, maxSize)
</span><span class="cx">     {
</span><ins>+        if (this._cachedMinSize === minSize &amp;&amp; this._cachedMaxSize === maxSize)
+            return;
+
+        this._cachedMinSize = minSize;
+        this._cachedMaxSize = maxSize;
+
</ins><span class="cx">         this._detailsMaxElement.textContent = WebInspector.UIString(&quot;Highest: %s&quot;).format(Number.isFinite(maxSize) ? Number.bytesToString(maxSize) : emDash);
</span><span class="cx">         this._detailsMinElement.textContent = WebInspector.UIString(&quot;Lowest: %s&quot;).format(Number.isFinite(minSize) ? Number.bytesToString(minSize) : emDash);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsMemoryTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -65,6 +65,7 @@
</span><span class="cx">         super.reset();
</span><span class="cx"> 
</span><span class="cx">         this._maxSize = 0;
</span><ins>+        this._cachedMaxSize = undefined;
</ins><span class="cx"> 
</span><span class="cx">         this._updateLegend();
</span><span class="cx">         this._chart.clear();
</span><span class="lines">@@ -76,6 +77,9 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><ins>+        if (!this.visible)
+            return;
+
</ins><span class="cx">         this._updateLegend();
</span><span class="cx">         this._chart.clear();
</span><span class="cx"> 
</span><span class="lines">@@ -165,6 +169,11 @@
</span><span class="cx"> 
</span><span class="cx">     _updateLegend()
</span><span class="cx">     {
</span><ins>+        if (this._cachedMaxSize === this._maxSize)
+            return;
+
+        this._cachedMaxSize = this._maxSize;
+
</ins><span class="cx">         if (!this._maxSize) {
</span><span class="cx">             this._legendElement.hidden = true;
</span><span class="cx">             this._legendElement.textContent = &quot;&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsMemoryTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -135,6 +135,10 @@
</span><span class="cx"> 
</span><span class="cx">         this._maxSize = 0;
</span><span class="cx"> 
</span><ins>+        this._cachedLegendRecord = null;
+        this._cachedLegendMaxSize = undefined;
+        this._cachedLegendCurrentSize = undefined;
+
</ins><span class="cx">         this._usageCircleChart.clear();
</span><span class="cx">         this._usageCircleChart.needsLayout();
</span><span class="cx">         this._clearUsageLegend();
</span><span class="lines">@@ -244,6 +248,11 @@
</span><span class="cx"> 
</span><span class="cx">     _updateUsageLegend(record)
</span><span class="cx">     {
</span><ins>+        if (this._cachedLegendRecord === record)
+            return;
+
+        this._cachedLegendRecord = record;
+
</ins><span class="cx">         for (let {type, size} of record.categories) {
</span><span class="cx">             let sizeElement = this._usageLegendSizeElementMap.get(type);
</span><span class="cx">             sizeElement.textContent = Number.isFinite(size) ? Number.bytesToString(size) : emDash;
</span><span class="lines">@@ -276,6 +285,12 @@
</span><span class="cx"> 
</span><span class="cx">     _updateMaxComparisonLegend(currentSize)
</span><span class="cx">     {
</span><ins>+        if (this._cachedLegendMaxSize === this._maxSize &amp;&amp; this._cachedLegendCurrentSize === currentSize)
+            return;
+
+        this._cachedLegendMaxSize = this._maxSize;
+        this._cachedLegendCurrentSize = currentSize;
+
</ins><span class="cx">         this._maxComparisonMaximumSizeElement.textContent = Number.isFinite(this._maxSize) ? Number.bytesToString(this._maxSize) : emDash;
</span><span class="cx">         this._maxComparisonCurrentSizeElement.textContent = Number.isFinite(currentSize) ? Number.bytesToString(currentSize) : emDash;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNavigationBarjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx">         this.element.addEventListener(&quot;keydown&quot;, this._keyDown.bind(this), false);
</span><span class="cx">         this.element.addEventListener(&quot;mousedown&quot;, this._mouseDown.bind(this), false);
</span><span class="cx"> 
</span><ins>+        this._forceLayout = false;
</ins><span class="cx">         this._minimumWidth = NaN;
</span><span class="cx">         this._navigationItems = [];
</span><span class="cx"> 
</span><span class="lines">@@ -160,8 +161,20 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    layout()
</del><ins>+    needsLayout()
</ins><span class="cx">     {
</span><ins>+        this._forceLayout = true;
+
+        super.needsLayout();
+    }
+
+    layout(layoutReason)
+    {
+        if (layoutReason !== WebInspector.View.LayoutReason.Resize &amp;&amp; !this._forceLayout)
+            return;
+
+        this._forceLayout = false;
+
</ins><span class="cx">         // Remove the collapsed style class to test if the items can fit at full width.
</span><span class="cx">         this.element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineOverviewGraph.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineOverviewGraph.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineOverviewGraph.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -65,6 +65,9 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><ins>+        if (!this.visible)
+            return;
+
</ins><span class="cx">         let secondsPerPixel = this.timelineOverview.secondsPerPixel;
</span><span class="cx">         let recordBarIndex = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsRenderingFrameTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -102,6 +102,9 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><ins>+        if (!this.visible)
+            return;
+
</ins><span class="cx">         if (!this._renderingFrameTimeline.records.length)
</span><span class="cx">             return;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScriptTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineOverviewGraph.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineOverviewGraph.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineOverviewGraph.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -52,6 +52,9 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><ins>+        if (!this.visible)
+            return;
+
</ins><span class="cx">         let secondsPerPixel = this.timelineOverview.secondsPerPixel;
</span><span class="cx">         let recordBarIndex = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineRecordBarjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js (198619 => 198620)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js        2016-03-24 07:13:05 UTC (rev 198619)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js        2016-03-24 08:10:01 UTC (rev 198620)
</span><span class="lines">@@ -51,7 +51,8 @@
</span><span class="cx"> 
</span><span class="cx">         // FIXME: Do a binary search for records that fall inside start and current time.
</span><span class="cx"> 
</span><del>-        for (var record of records) {
</del><ins>+        for (var i = 0; i &lt; records.length; ++i) {
+            var record = records[i];
</ins><span class="cx">             if (isNaN(record.startTime))
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="lines">@@ -99,7 +100,9 @@
</span><span class="cx">             var inactiveEndTime = NaN;
</span><span class="cx">             var inactiveRecords = [];
</span><span class="cx"> 
</span><del>-            for (var record of visibleRecords) {
</del><ins>+            for (var i = 0; i &lt; visibleRecords.length; ++i) {
+                var record = visibleRecords[i];
+
</ins><span class="cx">                 // Check if the previous record is far enough away to create the inactive bar.
</span><span class="cx">                 if (!isNaN(inactiveStartTime) &amp;&amp; inactiveStartTime + Math.max(inactiveEndTime - inactiveStartTime, minimumDuration) + minimumMargin &lt;= record.startTime) {
</span><span class="cx">                     createBarCallback(inactiveRecords, WebInspector.TimelineRecordBar.RenderMode.InactiveOnly);
</span><span class="lines">@@ -131,7 +134,8 @@
</span><span class="cx"> 
</span><span class="cx">         var startTimeProperty = usesActiveStartTime ? &quot;activeStartTime&quot; : &quot;startTime&quot;;
</span><span class="cx"> 
</span><del>-        for (var record of visibleRecords) {
</del><ins>+        for (var i = 0; i &lt; visibleRecords.length; ++i) {
+            var record = visibleRecords[i];
</ins><span class="cx">             var startTime = record[startTimeProperty];
</span><span class="cx"> 
</span><span class="cx">             // Check if the previous record is far enough away to create the active bar. We also create it now if the current record has no active state time.
</span><span class="lines">@@ -194,8 +198,6 @@
</span><span class="cx"> 
</span><span class="cx">         records = records || [];
</span><span class="cx"> 
</span><del>-        console.assert(records instanceof Array, &quot;records should be an array&quot;);
-
</del><span class="cx">         this._records = records;
</span><span class="cx"> 
</span><span class="cx">         // Assume all records are the same type.
</span></span></pre>
</div>
</div>

</body>
</html>