diff options
author | Nicholas Ray <nray@wikimedia.org> | 2020-10-08 10:10:34 -0600 |
---|---|---|
committer | Nicholas Ray <nray@wikimedia.org> | 2020-10-09 10:56:19 -0600 |
commit | ee22af6ef7f5b6be750c0819764caa1900fe361f (patch) | |
tree | cb6b552762aa8bbb12230fd13ef8b7bc73619cd6 /resources/src/mediawiki.searchSuggest | |
parent | d14ce36a8c6578fca8a38d010a6167d73849cffe (diff) | |
download | mediawikicore-ee22af6ef7f5b6be750c0819764caa1900fe361f.tar.gz mediawikicore-ee22af6ef7f5b6be750c0819764caa1900fe361f.zip |
Add client-side performance metrics for legacy search
As part of comparing Vue search with legacy search, we need to track how
long it takes a keypress to load and render search results for legacy
search (Vue search will perform the same metrics).
This commit adds the following metrics which will only be used in our
synthetic tests. We are not collecting RUM metrics at this time.
Marks:
* mwVectorLegacySearchLoadStart: Marks start of loading the search
module.
* mwVectorLegacySearchLoadEnd: Marks the end of loading the search
module.
Measures:
* mwVectorLegacySearchLoadStartToLoadEnd: Measures the time it takes to
load the search module.
* mwVectorLegacySearchLoadStartToFirstRender: Measures the time it takes
from the start of loading the search module to the first render of results.
* mwVectorLegacySearchQueryToRender: Measures the time it takes from
the start of the fetch to the render of search results.
Additional changes:
* Fixed a bug in loadSearchModule that added an unneeded `focusin` event
listener when the input has already received focus.
Bug: T251544
Change-Id: I0fa6b8904bd43c87a68e9161f00d686a0e588966
Diffstat (limited to 'resources/src/mediawiki.searchSuggest')
-rw-r--r-- | resources/src/mediawiki.searchSuggest/searchSuggest.js | 68 |
1 files changed, 64 insertions, 4 deletions
diff --git a/resources/src/mediawiki.searchSuggest/searchSuggest.js b/resources/src/mediawiki.searchSuggest/searchSuggest.js index 04262775a0e0..c5357305d5b8 100644 --- a/resources/src/mediawiki.searchSuggest/searchSuggest.js +++ b/resources/src/mediawiki.searchSuggest/searchSuggest.js @@ -4,11 +4,27 @@ ( function () { // eslint-disable-next-line no-jquery/no-map-util var searchNS = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( nsName, nsID ) { - if ( nsID >= 0 && mw.user.options.get( 'searchNs' + nsID ) ) { + if ( nsID >= 0 && mw.user.options.get( 'searchNs' + nsID ) ) { // Cast string key to number - return Number( nsID ); - } - } ); + return Number( nsID ); + } + } ), + // T251544: Collect search performance metrics to compare Vue search with + // mediawiki.searchSuggest performance. Marks and Measures will only be + // recorded on the Vector skin. + shouldTestSearch = !!( mw.config.get( 'skin' ) === 'vector' && + window.performance && + window.requestAnimationFrame && + performance.mark && + performance.measure && + performance.getEntriesByName && + performance.clearMarks ), + loadStartMark = 'mwVectorLegacySearchLoadStart', + queryMark = 'mwVectorLegacySearchQuery', + renderMark = 'mwVectorLegacySearchRender', + queryToRenderMeasure = 'mwVectorLegacySearchQueryToRender', + loadStartToFirstRenderMeasure = 'mwVectorLegacySearchLoadStartToFirstRender'; + mw.searchSuggest = { // queries the wiki and calls response with the result request: function ( api, query, response, maxRows, namespace ) { @@ -90,6 +106,20 @@ } ); } previousSearchText = searchText; + + if ( !shouldTestSearch ) { + return; + } + + // Clear past marks that are no longer relevant. This likely means that the + // search request failed or was cancelled. Whatever the reason, the mark + // is no longer needed since we are only interested in collecting the time + // from query to render. + if ( performance.getEntriesByName( queryMark ).length ) { + performance.clearMarks( queryMark ); + } + + performance.mark( queryMark ); } /** @@ -128,6 +158,36 @@ query: metadata.query, inputLocation: getInputLocation( context ) } ); + + if ( shouldTestSearch ) { + // Schedule the mark after the search results have rendered and are + // visible to the user. Two rAF's are needed for this since rAF will + // execute before the rendering steps happen (e.g. layout and paint). A + // nested rAF will execute after these rendering steps have completed + // and ensure the search results are visible to the user. + requestAnimationFrame( function () { + requestAnimationFrame( function () { + if ( !performance.getEntriesByName( queryMark ).length ) { + return; + } + + performance.mark( renderMark ); + performance.measure( queryToRenderMeasure, queryMark, renderMark ); + + // Measure from the start of the lazy load to the first render if we + // haven't already captured that info. + if ( performance.getEntriesByName( loadStartMark ).length && + !performance.getEntriesByName( loadStartToFirstRenderMeasure ).length ) { + performance.measure( loadStartToFirstRenderMeasure, loadStartMark, renderMark ); + } + + // The measures are the most meaningful info so we remove the marks + // after we have the measure. + performance.clearMarks( queryMark ); + performance.clearMarks( renderMark ); + } ); + } ); + } } // The function used to render the suggestions. |