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

chore(docs): docs app initialization performance #9204

Closed
wants to merge 10 commits into from

Conversation

petebacondarwin
Copy link
Contributor

Stage 1 - delay search index build for one second

Following in the best traditions of agile development. Here is a minimal improvement in the user experience when they appear at the docs website. The page now renders immediately but then locks the page after 1 sec while it builds the index. This is a slight UX improvement. The next stage is to move this processing to a WebWorker to prevent it blocking the main thread.

Related to #9203

This is in preparation for moving the work to a WebWorker but will also facilitate,
in the future, removing the `pagesData` angular module altogether.
This commit refactors how the search index is built. The docsSearch service
is now defined by a provider, which returns a different implementation of
the service depending upon whether the current browser supports WebWorkers
or now.

* **WebWorker supported**: The index is then built and stored in a new worker.
The service posts and receives messages to and from this worker to make
queries on the search index.

* **WebWorker no supported**: The index is built locally but with a 500ms
delay so that the initial page can render before the browser is blocked as
the index is built.
@petebacondarwin
Copy link
Contributor Author

Stage 2 - use a WebWorker if available

Depending upon whether WebWorkers are supported, the docsSearchProvider provides different implementation of the docsSearch service. If not supported then the previous implementation stands. If it is supported then the whole index building and querying is moved out into a WebWorker. This means that the browser is no longer blocked during bootstrap or at any time afterward. Also, it appears from anecdotal testing that generating the index in a WebWorker is actually even faster than in the normal thread. So there is a general performance gain all round.

The result is that for the majority of browsers (), there is a vast improvement to the startup time of the docs app.

The way that the new query implementation works is very robust. Querying the index is now asynchronous and the calling controller receives a promise for the results. If the index has not yet been built, queries will just return an empty result set. If the index is still being built then the promise will wait until the index has been built before resolving. It is unlikely that the user will manage to make a query before the index has been built, especially as we make a query for every key press in the search box. So even if the first couple of key presses are before the index has been built the subsequent key presses will return valid results.

Going Further

The experience on desktop is now good enough that I would say that the cost of improving the search index related performance further (caching in localStorage) is not worth the additional effort.

Using localStorage there would be no immediate memory usage improvement; in fact the extra storage of potentially multiple search indexes per version would add storage overhead. LocalStorage has capacity issues that would need to be worked around. Cache expiration issues would also need to be implemented.

It is worth spending some time testing the experience on mobile devices since these are most likely to show degradation, especially if they are not multiprocessor.

@petebacondarwin
Copy link
Contributor Author

There is a demo here: http://ci.angularjs.org/job/angular.js-pete/669/artifact/build/docs/api
How fast does this load on your machines?

@caitp
Copy link
Contributor

caitp commented Sep 22, 2014

pretty slow for the initial load, but almost instant for subsequent loads

@lgalfaso
Copy link
Contributor

same here, BTW, for some reason lunr.min.js is loaded twice, once from the page
addTag('script', {src: 'components/lunr.js-0.4.2/lunr.min.js' }, sync);
and the other from search.js
importScripts('../components/lunr.js-0.4.2/lunr.min.js');

@jeffbcross jeffbcross modified the milestones: 1.3.0-rc.3, 1.3.0-rc.4 Sep 22, 2014
petebacondarwin added a commit that referenced this pull request Sep 23, 2014
This commit refactors how the search index is built. The docsSearch service
is now defined by a provider, which returns a different implementation of
the service depending upon whether the current browser supports WebWorkers
or now.

* **WebWorker supported**: The index is then built and stored in a new worker.
The service posts and receives messages to and from this worker to make
queries on the search index.

* **WebWorker no supported**: The index is built locally but with a 500ms
delay so that the initial page can render before the browser is blocked as
the index is built.

Also the way that the current app is identified has been modified so we can
slim down the js data files (pages-data.js) to again improve startup time.

Closes #9204
Closes #9203
@petebacondarwin
Copy link
Contributor Author

BTW, for some reason lunr.min.js is loaded twice, once from the page addTag('script', {src: 'components/lunr.js-0.4.2/lunr.min.js' }, sync); and the other from search.js importScripts('../components/lunr.js-0.4.2/lunr.min.js');

@lgalfaso - this is because we need to have it in both contexts (main JS and web worker). It is not possible, I believe, to share the downloaded file. If we could guarantee that web workers were available then we could ditch the main JS download - or we could try to download it async.

@petebacondarwin petebacondarwin deleted the docs-refact branch November 24, 2016 09:20
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants