Changeset 201778 in webkit
- Timestamp:
- Jun 7, 2016 5:32:08 PM (8 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r201773 r201778 1 2016-06-07 Brian Burg <bburg@apple.com> 2 3 Web Inspector: reduce timer churn when processing many DOM.attributeModified messages 4 https://bugs.webkit.org/show_bug.cgi?id=158491 5 <rdar://problem/25561452> 6 7 Reviewed by Timothy Hatcher. 8 9 When the backend sends thousands of DOM.attributeModified events to the frontend, it 10 slows to a crawl. This is partly because redundant messages are being sent, and 11 because the frontend is taking too long to render attribute updates in the elements tab. 12 13 This patch is a first step to improve performance by reducing unnecessary work. It 14 coalesces all attribute state updates to only happen once per animation frame. This 15 reduces timer churn because we previously used a debouncing timer with interval of 0ms, 16 and that had to be cleared and restarted on every call. This change also eliminates 17 forced layouts when updating the selection highlights, since the DOM tree outline has 18 been reflowed by the time we start updating selections in a requestAnimationFrame callback. 19 20 There is still a lot of optimization to be done here, but this reduces the problem 21 considerably by keeping the event loop clear and making it obvious which selection 22 update operations are still too expensive. 23 24 * UserInterface/Base/Utilities.js: 25 Add a 'onNextFrame' proxy to Object. It works like debounce, except it coalesces calls 26 up until the next animation frame rather than a fixed timeout. It also does not extend 27 the timeout interval for each call. 28 29 * UserInterface/Views/DOMTreeUpdater.js: 30 (WebInspector.DOMTreeUpdater.prototype._attributesUpdated): 31 (WebInspector.DOMTreeUpdater.prototype._characterDataModified): 32 (WebInspector.DOMTreeUpdater.prototype._nodeInserted): 33 (WebInspector.DOMTreeUpdater.prototype._nodeRemoved): 34 (WebInspector.DOMTreeUpdater.prototype._updateModifiedNodes): 35 Update on the next frame rather than on a zero delay timeout. 36 37 * UserInterface/Views/TreeOutline.js: 38 (WebInspector.TreeOutline.WebInspector.TreeElement.prototype.didChange): 39 (WebInspector.TreeOutline.WebInspector.TreeElement.prototype._fireDidChange): 40 Update on the next frame rather than on a zero delay timeout. 41 1 42 2016-06-07 Nikita Vasilyev <nvasilyev@apple.com> 2 43 -
trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js
r201168 r201778 1274 1274 } 1275 1275 }); 1276 1277 const requestAnimationFrameSymbol = Symbol("peform-on-animation-frame"); 1278 const requestAnimationFrameProxySymbol = Symbol("perform-on-animation-frame-proxy"); 1279 1280 Object.defineProperty(Object.prototype, "onNextFrame", 1281 { 1282 get: function() 1283 { 1284 if (!this[requestAnimationFrameProxySymbol]) { 1285 this[requestAnimationFrameProxySymbol] = new Proxy(this, { 1286 get(target, property, receiver) { 1287 return (...args) => { 1288 let original = target[property]; 1289 console.assert(typeof original === "function"); 1290 1291 if (original[requestAnimationFrameSymbol]) 1292 return; 1293 1294 let performWork = () => { 1295 original[requestAnimationFrameSymbol] = undefined; 1296 original.apply(target, args); 1297 }; 1298 1299 original[requestAnimationFrameSymbol] = requestAnimationFrame(performWork); 1300 }; 1301 } 1302 }); 1303 } 1304 1305 return this[requestAnimationFrameProxySymbol]; 1306 } 1307 }); 1276 1308 })(); 1277 1309 -
trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeUpdater.js
r199790 r201778 58 58 this._recentlyModifiedNodes.push({node: event.data.node, updated: true, attribute: event.data.name}); 59 59 if (this._treeOutline._visible) 60 this. soon._updateModifiedNodes();60 this.onNextFrame._updateModifiedNodes(); 61 61 }, 62 62 … … 65 65 this._recentlyModifiedNodes.push({node: event.data.node, updated: true}); 66 66 if (this._treeOutline._visible) 67 this. soon._updateModifiedNodes();67 this.onNextFrame._updateModifiedNodes(); 68 68 }, 69 69 … … 72 72 this._recentlyModifiedNodes.push({node: event.data.node, parent: event.data.parent, inserted: true}); 73 73 if (this._treeOutline._visible) 74 this. soon._updateModifiedNodes();74 this.onNextFrame._updateModifiedNodes(); 75 75 }, 76 76 … … 79 79 this._recentlyModifiedNodes.push({node: event.data.node, parent: event.data.parent, removed: true}); 80 80 if (this._treeOutline._visible) 81 this. soon._updateModifiedNodes();81 this.onNextFrame._updateModifiedNodes(); 82 82 }, 83 83 … … 91 91 _updateModifiedNodes: function() 92 92 { 93 this._updateModifiedNodes.cancelDebounce();94 95 93 let updatedParentTreeElements = []; 96 94 for (let recentlyModifiedNode of this._recentlyModifiedNodes) { -
trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js
r196362 r201778 801 801 _fireDidChange() 802 802 { 803 this._didChangeTimeoutIdentifier = undefined;804 805 803 if (this.treeOutline) 806 804 this.treeOutline._treeElementDidChange(this); … … 812 810 return; 813 811 814 // Prevent telling the TreeOutline multiple times in a row by delaying it with a timeout. 815 if (!this._didChangeTimeoutIdentifier) 816 this._didChangeTimeoutIdentifier = setTimeout(this._fireDidChange.bind(this), 0); 812 this.onNextFrame._fireDidChange(); 817 813 } 818 814
Note: See TracChangeset
for help on using the changeset viewer.