Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

perf(md-tooltip) use MutationObserver instead of watcher if available #7822

Closed

Conversation

clshortfuse
Copy link
Contributor

use watcher on mdVisible only if being used

fixes #4033

improved version of #4441

}

function configureWatchers ()
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Braces should be in the same line.

@clshortfuse
Copy link
Contributor Author

I believe I don't have to call scope.visibleWatcher() in onDestroy, but somebody correct me if I'm wrong.

use watcher on mdVisible only if being used

braces on same line

manually fire change if not watcher is present
if (isVisible) showTooltip();
else hideTooltip();
});
if (element[0] && 'MutationObserver' in $window) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use MutationObserver instead of $attrs.$observe( ) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While $observe is technically faster than $watch since it's a string comparison vs an object/expression evaluation, both are checked synchronously every $digest.

MutationObserver is handled by the browser and signaled asynchronously.

@ThomasBurleson
Copy link
Contributor

Solution appears to be complex. What are the justifications and perf gains?

@ThomasBurleson ThomasBurleson added the needs: team discussion This issue requires a decision from the team before moving forward. label Apr 5, 2016
@clshortfuse
Copy link
Contributor Author

I'll write a codepen to show the gains of this and the md-menu change.

I use this in a production environment. With the solution I built, virtual repeat is not possible, and I have a table with 100s of rows and an md-tooltip on icons and an md-menu item on each row. Essentially, a 500 row table will have 1/4x the amount of watchers, going from 2000 down to 500 with no features lost. Watchers are processed every digest or apply and 2000 watchers will bring even an i7 to its knees.

The important thing is to make sure that no features are lost, which I think the code is fine in this regard.

@clshortfuse
Copy link
Contributor Author

A short explanation of the code is as follows:

md-direction is a raw value tied to an attribute in the md-tooltip element. Since this variable is raw text, we can use MutationObserver to get a "push notification" from the browser when it changes instead of looping every digest to check if the attribute changed (what Angular does)

md-visible is a reference value that needs to be checked by angular. Because tying md-visible to a value is optional in md-tooltip, the code will only use a watcher if the attribute is being used. If the attribute is not set at runtime, a MutationObserver is used to receive a "push notification" if the user decides to start using the attribute, which then creates the watcher.

If MutationObserver is not available, the code will fallback to Angular's regular checks every digest loop.

@clshortfuse
Copy link
Contributor Author

Okay, here are the code pens:

Here's 1.0.7 which is the standard way of using two watchers per tooltip: http://codepen.io/shortfuse/pen/LNOdvW

In my table of 1000 bind-once rows, it increments the watcher count from 13 to 4000 (2 per row).

On my fork which doesn't use watchers, the watcher count stays the same at 13.
http://codepen.io/shortfuse/pen/RajMOx

I set it to a high number to illustrate the performance effects. Please disregard any CSS changes in my fork.

@ThomasBurleson ThomasBurleson added the needs: review This PR is waiting on review from the team label Apr 5, 2016
@ThomasBurleson
Copy link
Contributor

@jelbourn - please review. Seems like a reasonable perf improvement for tooltips in large tables.

@@ -92,19 +92,42 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe
content.css('transform-origin', origin);
}

function onVisibleChanged (isVisible) {
if (isVisible) showTooltip();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing braces
(here and elsewhere)

ilovett pushed a commit to ilovett/material that referenced this pull request Apr 22, 2016
… use watcher on mdVisible only if being used

braces on same line

manually fire change if not watcher is present

Closes angular#7822
bradrich added a commit to bradrich/material that referenced this pull request Dec 21, 2016
Fixes angular#10162 - When the position was changed dynamically the resulting
tooltip's panel would retain the position classes on it's panelEl.
Now when creating and recreating the tooltip with a different position
class due to a position change, the panel will grab that tracked panel
and update its configuration object so that the new position class can
be used.

Fixes angular#10157 - There was a `mdDirection` watcher that was deleted due
to a rebase/timing issue when moving to the `mdPanel` API. Reference
to previous PR: angular#7822.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
needs: review This PR is waiting on review from the team needs: team discussion This issue requires a decision from the team before moving forward.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

(perf)md-tooltip uses angular watcher per item
4 participants