Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Map] Improve web performances by not calling "createInfoWindow" if unnecessary #2083

Draft
wants to merge 1 commit into
base: 2.x
Choose a base branch
from

Conversation

Kocal
Copy link
Member

@Kocal Kocal commented Aug 18, 2024

Q A
Bug fix? no
New feature? yes
Issues Fix #...
License MIT

This afternoon we spoke a bit with @simondaigre, and he told me about InfoWindow performance issues when you have too many of them (and depending your device).

If we have 1.000 InfoWindow, hidden by default and only visible after clicking on a marker, why should be only create the InfoWindow at that time?

This PR introduce lazy-creation of InfoWindow, it should improve web-performances on the user's browsers.

I've used the following PHP code:

       $map = (new Map())
            ->center(new Point(0, 0))
            ->zoom(2)
            ->fitBoundsToMarkers()
            ->options(new GoogleOptions(
                mapId: 'XXX',
            ))
        ;

        for ($i = 0; $i < 1_000; $i++) {
            $map->addMarker(
                new Marker(
                    position: new Point(random_int(-90, 90), random_int(-180, 180)),
                    title: 'Marker ' . $i,
                    infoWindow: new InfoWindow(
                        content: 'Info window ' . $i,
                        opened: $i % 499 === 0
                    )
                )
            );
        }

Benchmarks

I've did some benchmarks for both Google and Leaflet:

  • with 1.000 markers,
  • on a Macbook M1 Pro, CPU Throttle x6

Google

Before After
Capture d’écran 2024-08-18 à 18 28 54 Capture d’écran 2024-08-18 à 18 30 29

connect() takes 936ms instead of ~1,80s, we won ~900ms.

Leaflet

Before After
Capture d’écran 2024-08-18 à 18 45 10 Capture d’écran 2024-08-18 à 18 45 28

connect() takes ~1s instead of ~1,20s, we won ~200ms


The next steps for performance optimizations are:

  • Lazyloading markers and infoWindows, in order to keep a good TTFB
  • Clusters!

@carsonbot carsonbot added Feature New Feature Status: Needs Review Needs to be reviewed labels Aug 18, 2024
Comment on lines +45 to +47
marker.on('click', () => {
this.createInfoWindow({ definition: infoWindow, marker, onMarkerClick: true });
});
Copy link
Member

Choose a reason for hiding this comment

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

Does not seem a good idea to run every time.

Copy link
Member Author

Choose a reason for hiding this comment

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

What do you mean?

Copy link
Member

Choose a reason for hiding this comment

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

"createInfoWindow" will be called on every "click" ?

Copy link
Member Author

@Kocal Kocal Aug 20, 2024

Choose a reason for hiding this comment

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

Ah, yes you're right.

Hum, I may have better ideas to rewrite the PR, but I don't have time right now, let's put it in draft.

@@ -111,12 +111,14 @@ export default abstract class<
protected createInfoWindow({
definition,
marker,
onMarkerClick = false,
Copy link
Member

Choose a reason for hiding this comment

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

Not sure this should be exposed like this, seems to complexify the contract, while not beeing this "explanatory"

Comment on lines +157 to 163
if (definition.opened || onMarkerClick) {
infoWindow.open({
map: this.map,
shouldFocus: false,
anchor: marker,
});
}
Copy link
Member

Choose a reason for hiding this comment

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

Confusing to me... this mixes runtime values and definition values

@smnandre
Copy link
Member

I feel like the current implementation could be improved, but i don't think we could/should avoid exposing this internal code.. and the loop seems a bit odd.

Why not having separate create / open methods ?

@Kocal Kocal marked this pull request as draft August 20, 2024 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature New Feature Status: Needs Review Needs to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants