Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(824)

Unified Diff: third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js

Issue 2324293002: Roll performance-oriented iron-list changes (Closed)
Patch Set: test fix courtesy of michaelpg@ Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js
index 57f1260dd4598a7df9a823652a56c487f9d078cd..6159e4946800d830b155a8aee6043672e6d24d7d 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js
@@ -234,17 +234,6 @@
_collection: null,
/**
- * True if the current item list was rendered for the first time
- * after attached.
- */
- _itemsRendered: false,
-
- /**
- * The page that is currently rendered.
- */
- _lastPage: null,
-
- /**
* The max number of pages to render. One page is equivalent to the height of the list.
*/
_maxPages: 3,
@@ -287,6 +276,11 @@
_rowHeight: 0,
/**
+ * The cost of stamping a template in ms.
+ */
+ _templateCost: 0,
+
+ /**
* The bottom of the physical content.
*/
get _physicalBottom() {
@@ -405,7 +399,7 @@
* True if the current list is visible.
*/
get _isVisible() {
- return this.scrollTarget && Boolean(this.scrollTarget.offsetWidth || this.scrollTarget.offsetHeight);
+ return Boolean(this.offsetWidth || this.offsetHeight);
},
/**
@@ -462,6 +456,7 @@
get _defaultScrollTarget() {
return this;
},
+
get _virtualRowCount() {
return Math.ceil(this._virtualCount / this._itemsPerRow);
},
@@ -480,14 +475,15 @@
attached: function() {
this.updateViewportBoundaries();
- this._render();
+ if (this._physicalCount === 0) {
+ this._debounceTemplate(this._render);
+ }
// `iron-resize` is fired when the list is attached if the event is added
// before attached causing unnecessary work.
this.listen(this, 'iron-resize', '_resizeHandler');
},
detached: function() {
- this._itemsRendered = false;
this.unlisten(this, 'iron-resize', '_resizeHandler');
},
@@ -612,7 +608,7 @@
}
if (recycledTiles === 0) {
- // Try to increase the pool if the list's client height isn't filled up with physical items
+ // Try to increase the pool if the list's client isn't filled up with physical items
if (physicalBottom < scrollBottom || this._physicalTop > scrollTop) {
this._increasePoolIfNeeded();
}
@@ -629,29 +625,25 @@
* @param {!Array<number>=} movingUp
*/
_update: function(itemSet, movingUp) {
- // manage focus
this._manageFocus();
- // update models
this._assignModels(itemSet);
- // measure heights
this._updateMetrics(itemSet);
- // adjust offset after measuring
+ // Adjust offset after measuring.
if (movingUp) {
while (movingUp.length) {
var idx = movingUp.pop();
this._physicalTop -= this._getPhysicalSizeIncrement(idx);
}
}
- // update the position of the items
this._positionItems();
- // set the scroller size
this._updateScrollerSize();
- // increase the pool of physical items
this._increasePoolIfNeeded();
},
/**
* Creates a pool of DOM elements and attaches them to the local dom.
+ *
+ * @param {number} size Size of the pool
*/
_createPool: function(size) {
var physicalItems = new Array(size);
@@ -661,7 +653,7 @@
for (var i = 0; i < size; i++) {
var inst = this.stamp(null);
// First element child is item; Safari doesn't support children[0]
- // on a doc fragment
+ // on a doc fragment.
physicalItems[i] = inst.root.querySelector('*');
Polymer.dom(this).appendChild(inst.root);
}
@@ -678,32 +670,39 @@
if (this._viewportHeight === 0) {
return false;
}
- // Base case 2: If the physical size is optimal and the list's client height is full
+ var self = this;
+ var isClientFull = this._physicalBottom >= this._scrollBottom &&
+ this._physicalTop <= this._scrollPosition;
+
+ // Base case 2: if the physical size is optimal and the list's client height is full
// with physical items, don't increase the pool.
- var isClientHeightFull = this._physicalBottom >= this._scrollBottom && this._physicalTop <= this._scrollPosition;
- if (this._physicalSize >= this._optPhysicalSize && isClientHeightFull) {
+ if (this._physicalSize >= this._optPhysicalSize && isClientFull) {
return false;
}
- // this value should range between [0 <= `currentPage` <= `_maxPages`]
- var currentPage = Math.floor(this._physicalSize / this._viewportHeight);
-
- if (currentPage === 0) {
- // fill the first page
- this._debounceTemplate(this._increasePool.bind(this, Math.round(this._physicalCount * 0.5)));
- } else if (this._lastPage !== currentPage && isClientHeightFull) {
- // paint the page and defer the next increase
- // wait 16ms which is rough enough to get paint cycle.
- Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', this._increasePool.bind(this, this._itemsPerRow), 16));
- } else {
- // fill the rest of the pages
- this._debounceTemplate(this._increasePool.bind(this, this._itemsPerRow));
+ var maxPoolSize = Math.round(this._physicalCount * 0.5);
+ // Increase the pool synchronously until the client is filled.
+ if (!isClientFull) {
+ this._debounceTemplate(this._increasePool.bind(this, maxPoolSize));
+ return true;
}
-
- this._lastPage = currentPage;
-
+ this._yield(function() {
+ self._increasePool(Math.min(maxPoolSize, Math.max(1, Math.round(50 / self._templateCost))));
+ });
return true;
},
+ _yield: function(cb) {
+ var g = window;
+ var handle = g.requestIdleCallback ? g.requestIdleCallback(cb) : g.setTimeout(cb, 16);
+ // Polymer/issues/3895
+ Polymer.dom.addDebouncer(/** @type {!Polymer.Debouncer} */({
+ complete: function() {
+ g.cancelIdleCallback ? g.cancelIdleCallback(handle) : g.clearTimeout(handle);
+ cb();
+ }
+ }));
+ },
+
/**
* Increases the pool size.
*/
@@ -715,17 +714,16 @@
);
var prevPhysicalCount = this._physicalCount;
var delta = nextPhysicalCount - prevPhysicalCount;
+ var ts = window.performance.now();
if (delta <= 0) {
return;
}
-
+ // Concat arrays in place.
[].push.apply(this._physicalItems, this._createPool(delta));
[].push.apply(this._physicalSizes, new Array(delta));
-
this._physicalCount = prevPhysicalCount + delta;
-
- // update the physical start if we need to preserve the model of the focused item.
+ // Update the physical start if it needs to preserve the model of the focused item.
// In this situation, the focused item is currently rendered and its model would
// have changed after increasing the pool if the physical start remained unchanged.
if (this._physicalStart > this._physicalEnd &&
@@ -734,19 +732,19 @@
this._physicalStart = this._physicalStart + delta;
}
this._update();
+ this._templateCost = (window.performance.now() - ts) / delta;
},
/**
- * Render a new list of items. This method does exactly the same as `update`,
- * but it also ensures that only one `update` cycle is created.
+ * Render a new list of items.
*/
_render: function() {
- var requiresUpdate = this._virtualCount > 0 || this._physicalCount > 0;
-
- if (this.isAttached && !this._itemsRendered && this._isVisible && requiresUpdate) {
- this._lastPage = 0;
- this._update();
- this._itemsRendered = true;
+ if (this.isAttached && this._isVisible) {
+ if (this._physicalCount === 0) {
+ this._increasePool(DEFAULT_PHYSICAL_COUNT);
+ } else {
+ this._update();
+ }
}
},
@@ -762,7 +760,6 @@
props[this.indexAs] = true;
props[this.selectedAs] = true;
props.tabIndex = true;
-
this._instanceProps = props;
this._userTemplate = Polymer.dom(this).querySelector('template');
@@ -863,7 +860,6 @@
*/
_itemsChanged: function(change) {
if (change.path === 'items') {
- // reset items
this._virtualStart = 0;
this._physicalTop = 0;
this._virtualCount = this.items ? this.items.length : 0;
@@ -871,31 +867,22 @@
this._physicalIndexForKey = {};
this._firstVisibleIndexVal = null;
this._lastVisibleIndexVal = null;
-
+ this._physicalCount = this._physicalCount || 0;
+ this._physicalItems = this._physicalItems || [];
+ this._physicalSizes = this._physicalSizes || [];
+ this._physicalStart = 0;
this._resetScrollPosition(0);
this._removeFocusedItem();
- // create the initial physical items
- if (!this._physicalItems) {
- this._physicalCount = Math.max(1, Math.min(DEFAULT_PHYSICAL_COUNT, this._virtualCount));
- this._physicalItems = this._createPool(this._physicalCount);
- this._physicalSizes = new Array(this._physicalCount);
- }
-
- this._physicalStart = 0;
+ this._debounceTemplate(this._render);
} else if (change.path === 'items.splices') {
-
this._adjustVirtualIndex(change.value.indexSplices);
this._virtualCount = this.items ? this.items.length : 0;
+ this._debounceTemplate(this._render);
} else {
- // update a single item
this._forwardItemPath(change.path.split('.').slice(1).join('.'), change.value);
- return;
}
-
- this._itemsRendered = false;
- this._debounceTemplate(this._render);
},
/**
@@ -1008,7 +995,7 @@
*/
_updateMetrics: function(itemSet) {
// Make sure we distributed all the physical items
- // so we can measure them
+ // so we can measure them.
Polymer.dom.flush();
var newPhysicalSize = 0;
@@ -1033,7 +1020,7 @@
this._physicalSize = this._physicalSize + newPhysicalSize - oldPhysicalSize;
}
- // update the average if we measured something
+ // Update the average if it measured something.
if (this._physicalAverageCount !== prevAvgCount) {
this._physicalAverage = Math.round(
((prevPhysicalAvg * prevAvgCount) + newPhysicalSize) /
@@ -1064,23 +1051,17 @@
var rowOffset = (this._viewportWidth - totalItemWidth) / 2;
this._iterateItems(function(pidx, vidx) {
-
var modulus = vidx % this._itemsPerRow;
var x = Math.floor((modulus * this._itemWidth) + rowOffset);
-
this.translate3d(x + 'px', y + 'px', 0, this._physicalItems[pidx]);
-
if (this._shouldRenderNextRow(vidx)) {
y += this._rowHeight;
}
-
});
} else {
this._iterateItems(function(pidx, vidx) {
-
this.translate3d(0, y + 'px', 0, this._physicalItems[pidx]);
y += this._physicalSizes[pidx];
-
});
}
},
@@ -1150,7 +1131,7 @@
forceUpdate = forceUpdate || this._scrollPosition >= this._estScrollHeight - this._physicalSize;
forceUpdate = forceUpdate || this.grid && this.$.items.style.height < this._estScrollHeight;
- // amortize height adjustment, so it won't trigger repaints very often
+ // Amortize height adjustment, so it won't trigger large repaints too often.
if (forceUpdate || Math.abs(this._estScrollHeight - this._scrollHeight) >= this._optPhysicalSize) {
this.$.items.style.height = this._estScrollHeight + 'px';
this._scrollHeight = this._estScrollHeight;
@@ -1179,44 +1160,38 @@
if (typeof idx !== 'number' || idx < 0 || idx > this.items.length - 1) {
return;
}
+
Polymer.dom.flush();
// Items should have been rendered prior scrolling to an index.
- if (!this._itemsRendered) {
+ if (this._physicalCount === 0) {
return;
}
idx = Math.min(Math.max(idx, 0), this._virtualCount-1);
- // update the virtual start only when needed
+ // Update the virtual start only when needed.
if (!this._isIndexRendered(idx) || idx >= this._maxVirtualStart) {
this._virtualStart = this.grid ? (idx - this._itemsPerRow * 2) : (idx - 1);
}
- // manage focus
this._manageFocus();
- // assign new models
this._assignModels();
- // measure the new sizes
this._updateMetrics();
- // estimate new physical offset
+ // Estimate new physical offset.
this._physicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * this._physicalAverage;
var currentTopItem = this._physicalStart;
var currentVirtualItem = this._virtualStart;
var targetOffsetTop = 0;
var hiddenContentSize = this._hiddenContentSize;
- // scroll to the item as much as we can
+ // scroll to the item as much as we can.
while (currentVirtualItem < idx && targetOffsetTop <= hiddenContentSize) {
targetOffsetTop = targetOffsetTop + this._getPhysicalSizeIncrement(currentTopItem);
currentTopItem = (currentTopItem + 1) % this._physicalCount;
currentVirtualItem++;
}
- // update the scroller size
this._updateScrollerSize(true);
- // update the position of the items
this._positionItems();
- // set the new scroll position
this._resetScrollPosition(this._physicalTop + this._scrollerPaddingTop + targetOffsetTop);
- // increase the pool of physical items if needed
this._increasePoolIfNeeded();
- // clear cached visible index
+ // clear cached visible index.
this._firstVisibleIndexVal = null;
this._lastVisibleIndexVal = null;
},
@@ -1245,7 +1220,7 @@
this.updateViewportBoundaries();
this._render();
- if (this._itemsRendered && this._physicalItems && this._isVisible) {
+ if (this._physicalCount > 0 && this._isVisible) {
this._resetAverage();
this.scrollToIndex(this.firstVisibleIndex);
}
« no previous file with comments | « third_party/polymer/v1_0/components-chromium/iron-list/bower.json ('k') | third_party/polymer/v1_0/components_summary.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698