esm7 / obsidian-map-view

Interactive map view for Obsidian.md

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Obsidian performance degrades due to monitoring all DOM changes

kepano opened this issue · comments

It looks like Map View monitors all DOM changes. As a result loading the Community Plugins view causes Obsidian to load slowly. You can reproduce the issue by going to Community Plugins → Browse

See profiler results below

Screenshot_2024-01-03_at_10 56 33_AM

Screenshot_2024-01-03_at_10 58 57_AM

I have done a quick analysis and this seems to be coming from fontawesome which monitors all DOM insertions using a MutationObserver, and running extensive querySelectorAll's on the DOM changes. Suggest replacing FontAwesome with something else.

commented

I have done a quick analysis and this seems to be coming from fontawesome which monitors all DOM insertions using a MutationObserver, and running extensive querySelectorAll's on the DOM changes. Suggest replacing FontAwesome with something else.

This will break years of users' settings, as nearly all Map View users define map marker rules, and these mention specific icon names to be used.
Wouldn't a better approach be to open an issue for FontAwesome?

Ah I guess you're too deep into it. In that case I suggest look into how Fontawesome is setup, and see if you can disable its global hook that monitors all DOM insertion events. You should only need it for the elements under your plugin's control.

commented

A quick update.

First, the facts.
I browsed through the FontAwesome documentation and issues and there doesn't seem to be a way around their nasty MutationObserver when using their JS+SVG method of rendering icons.
There is the alternative of using the Web Fonts method for rendering the icons. This is how Map View used to work, but it becomes slow to a crawl when using maps with thousands of markers, where the JS+SVG method (together with some central caching) is blazing fast, so I switched to it in Map View 3.0.0.
So: JS+SVG = a necessary MutationObserver, great performance with any number of markers, but an Obsidian slow-down. Web Fonts = no MutationObserver, no Obsidian slow-down, but the plugin is unusable above some scale.

The long-term:
I'm starting to offer an alternative to FontAwesome. The upcoming version of Map View will support emoji map markers (#218).

Now the dilemma.
@lishid I'd love to get some feedback about whether you think this issue's affect on the Obsidian ecosystem is meaningful enough to maintain both of the FontAwesome implementations, have the Web Fonts implementation be the default, but let the user switch to JS+SVG if it gets too slow.
I know it sounds like the best of both worlds, but it introduces meaningful complexity that I don't want to take lightly.

Is there no way to disable the MutationObserver? I would first consider any way to get a reference to it and make it un-observe globally, but failing that I would also consider the possibility of modifying the library's source code prior to embedding it into your plugin code (since it's bundled).

Ideally the MutationObserver would be somehow exposed so that instead of observing every single mutation in the entire app, it would only observe any views you create (or alternatively, if the API allows, for you to proactively register or call to have an icon rendered).

commented

I'll inspect the source code more thoroughly by your suggestion, but I'm not optimistic, since the option to observe more narrowly for performance reasons was discussed it in the FontAwesome repo and in several posts online and the only solution mentioned was to use Web Fonts.

According to the docs here there is an option to set mutation observations to off: https://fontawesome.com/docs/apis/javascript/configuration

It does however require you to use fontawesome-svg-core instead of all, which is a bit more involved in the setup as you have to then setup your own mutation observer for your own elements (if you still want to observe for mutations) as it was originally written around here: https://github.com/FortAwesome/Font-Awesome/blob/a1232e34553634c5363aa62c8d1b02161a4438e1/js-packages/%40fortawesome/fontawesome-svg-core/index.mjs#L1923

As a question aside, when unloading your plugin, do you actually have code to clean up FontAwesome (unhook it somehow or remove its event listeners/mutation observers)? It doesn't seem you have anything in onunload so I am assuming your plugin doesn't cleanly unload itself and require a full app restart to take effect when disabling or updating?

commented

I made the needed changes (which included some rewrite of how the plugin uses FA, but it was well within reason), and happy to report it seems to work great! No mutation observer is used at all and Map View no longer causes a delay on Community Plugins → Browse.

Regarding your other question, I guess I was naive about how Font Awesome works, and maybe that's also the case about other packages I am using (the immediate suspect is Leaflet.js). I'll take a note to investigate which of these have side effects that need special care in unloading.

Nice!

commented

Released 5.0.0 with this fix.