[webkit-reviews] review denied: [Bug 193605] Web Inspector: Frontend performance is very slow reloading theverge.com - 50% of time in TreeOutline _indexOfTreeElement : [Attachment 361980] Patch

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Feb 13 23:18:41 PST 2019


Devin Rousso <drousso at apple.com> has denied Matt Baker <mattbaker at apple.com>'s
request for review:
Bug 193605: Web Inspector: Frontend performance is very slow reloading
theverge.com - 50% of time in TreeOutline _indexOfTreeElement
https://bugs.webkit.org/show_bug.cgi?id=193605

Attachment 361980: Patch

https://bugs.webkit.org/attachment.cgi?id=361980&action=review




--- Comment #33 from Devin Rousso <drousso at apple.com> ---
Comment on attachment 361980
  --> https://bugs.webkit.org/attachment.cgi?id=361980
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=361980&action=review

r-, as this breaks selection in the Network table.  Everything else looks
great, although I'd like to see a followup.  Awesome work!

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:32
> +	   console.assert(typeof comparator === "function");

NIT: this should be below the `delegate` assertion, since it's listed after in
the parameters.

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:35
> +	   this._comparator = comparator;

Ditto (>32).

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:136
> +		   let previous = this._previousSelectableItem(item);
> +		   let next = this._nextSelectableItem(item);
> +
> +		   while (!this.hasSelectedItem(previous) &&
!this.hasSelectedItem(next)) {
> +		       previous = this._previousSelectableItem(previous);
> +		       next = this._nextSelectableItem(next);
>		   }
> +
> +		   if (this.hasSelectedItem(previous))
> +		       this._lastSelectedItem = previous;
> +		   else if (this.hasSelectedItem(next))
> +		       this._lastSelectedItem = next;

It could be potentially costly to try to "eagerly" find the closest item in
_both_ directions _at the same time_.  I think we should be a bit more
"incremental", meaning we should only try one thing at a time.

    let previous = item;
    let next = item;
    while (!this._lastSelectedItem && previous && next) {
	previous = this._previousSelectableItem(previous);
	if (this.hasSelectedItem(previous)) {
	    this._lastSelectedItem = previous;
	    break;
	}

	next = this._nextSelectableItem(next);
	if (this.hasSelectedItem(next)) {
	    this._lastSelectableItem = next;
	    break;
	}
    }

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:167
> -    removeSelectedItems()
> +    willRemoveSelectedItems()

I personally think that `removeSelectedItems` is a better name, as it is
"removing" the selected items from this controller.  Adding "will" makes me
think that there's some sort of timeout/rAF that will "delay"  the removal. 
None of the callers have any sort of "will" (or future tense) naming either, so
I think it makes sense to match (e.g. no "will").

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:172
> +	   let orderedSelection =
Array.from(this._selectedItems).sort(this._comparator);

Rather than sort the entire list of selected items, couldn't we just find the
first/last item (e.g. some sort of `min` and `max` for the array)?  I've
written utilities functions for something like this in the past.

    Object.defineProperty(Array.prototype, "min",
    {
	value(comparator)
	{
	    function defaultComparator(a, b)
	    {
		return a - b;
	    }
	    comparator = comparator || defaultComparator;

	    let min = 0;
	    for (let i = 1; i < this.length; ++i) {
		if (comparator(this[min], this[i]) > 0)
		    min = i;
	    }
	    return this[min];
	},
    });

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:175
> +	   let lastSelectedItem = orderedSelection.lastValue;

Ditto (>172).

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:369
>	   if (this._suppressSelectionDidChange ||
!this._delegate.selectionControllerSelectionDidChange)

NIT: we should remove the
`!this._delegate.selectionControllerSelectionDidChange` check if we assert that
it exists in thee constructor.

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:383
> +	       if (current === lastItem)

We should assert that if `lastItem` is provided, it is included in `items`
(e.g. to cover the case where we `lastItem` isn't reachable).

> Source/WebInspectorUI/UserInterface/Controllers/SelectionController.js:394
> +	       if (current === lastItem)

Ditto (>383), except we'd want to assert that it's not included in `items`.

> Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js:86
> +	   if (index < 0 || index >= this._cookies.length)
> +	       return null;

This check seems unnecessary.  If anything, we should just be asserting, as
`undefined` is effectively equivalent to `null` for our typical falsy checks.

> Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js:327
> +	       if (!treeElement.__closeTagProxyObject) {

Style: unnecessary brackets.

> Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js:328
> +		   treeElement.__closeTagProxyObject = {treeElement};

Can we use the `__treeElementIdentifier` instead?  Regardless, I think we
should always have a `__` prefix, as we're effectively tacking on a view object
to a model object (I realize that this is a "fake" model object, but the
principle stands nonetheless).	If not, maybe we could use a different key,
like `__proxyObjectTreeElement`?

> Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js:332
> +	   return this._rowIndexForRepresentedObject(object);

This is not the right function to use.	`_rowIndexForRepresentedObject` is only
supposed to be used with actual model objects (e.g. `Resource` or `Node`), not
the "bag-of-stuff" objects used by the Network table.  You should just use
`this._filteredEntries.indexOf(object)`.

> Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js:338
> +	   if (index < 0 || index >= this._filteredEntries.length)
> +	       return null;

Ditto (>CookieStorageContentView.js:85).

> Source/WebInspectorUI/UserInterface/Views/Table.js:1421
> +

Style: extra newline.

> Source/WebInspectorUI/UserInterface/Views/Table.js:1423
> +	       if (rowIndexes.binaryIndexOf(index) >= 0) {

Clever!

> Source/WebInspectorUI/UserInterface/Views/Table.js:-1414
> -	   this._selectionController.didRemoveItems(rowIndexes);

This slightly scares me, as it assumes that the caller deselects an item before
it is removed.	I think we should either find some way of asserting (inside
`SelectionController`) that removed items aren't selected or not remove
`didRemoveItems` and have `SelectionController` simply remove items from its
set.

> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:60
> +	   let comparator = (a, b) => {

Nicely written!

> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:-349
> -	       treeOutline._selectionController.didRemoveItems(removedIndexes);

Ditto (<Table.js:1414).

> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:-397
> -		  
treeOutline._selectionController.didRemoveItems(removedIndexes);

Ditto (<Table.js:1414).

> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:848
> +		   treeElement.listItemElement.classList.remove("selected");

Style: missing newline after.

> Source/WebInspectorUI/UserInterface/Views/TreeOutline.js:858
> +		   treeElement.listItemElement.classList.add("selected");

Style: missing newline after.


More information about the webkit-reviews mailing list