aboutsummaryrefslogtreecommitdiffstats
path: root/resources/src
diff options
context:
space:
mode:
Diffstat (limited to 'resources/src')
-rw-r--r--resources/src/mediawiki.page.ready/ready.js36
-rw-r--r--resources/src/mediawiki.searchSuggest/searchSuggest.js68
2 files changed, 97 insertions, 7 deletions
diff --git a/resources/src/mediawiki.page.ready/ready.js b/resources/src/mediawiki.page.ready/ready.js
index c302dbe7e3e3..dbfe9d3b2aee 100644
--- a/resources/src/mediawiki.page.ready/ready.js
+++ b/resources/src/mediawiki.page.ready/ready.js
@@ -161,20 +161,50 @@ function isSearchInput( element ) {
* @param {string} moduleName Name of a module
*/
function loadSearchModule( moduleName ) {
+ // T251544: Collect search performance metrics to compare Vue search with
+ // mediawiki.searchSuggest performance. Marks and Measures will only be
+ // recorded on the Vector skin.
+ //
+ // Vue search isn't loaded through this function so we are only collecting
+ // legacy search performance metrics here.
+ var shouldTestSearch = !!( moduleName === 'mediawiki.searchSuggest' &&
+ mw.config.get( 'skin' ) === 'vector' &&
+ window.performance &&
+ performance.mark &&
+ performance.measure &&
+ performance.getEntriesByName ),
+ loadStartMark = 'mwVectorLegacySearchLoadStart',
+ loadEndMark = 'mwVectorLegacySearchLoadEnd';
+
+ function requestSearchModule() {
+ if ( shouldTestSearch ) {
+ performance.mark( loadStartMark );
+ }
+ mw.loader.using( moduleName, function () {
+ if ( shouldTestSearch && performance.getEntriesByName( loadStartMark ).length ) {
+ performance.mark( loadEndMark );
+ performance.measure( 'mwVectorLegacySearchLoadStartToLoadEnd', loadStartMark, loadEndMark );
+ }
+ } );
+ }
+
// Load the module once a search input is focussed.
function eventListener( e ) {
if ( isSearchInput( e.target ) ) {
- mw.loader.load( moduleName );
+ requestSearchModule();
+
document.removeEventListener( 'focusin', eventListener );
}
}
- document.addEventListener( 'focusin', eventListener );
// Load the module now if the search input is already focused,
// because the user started typing before the JavaScript arrived.
if ( document.activeElement && isSearchInput( document.activeElement ) ) {
- mw.loader.load( moduleName );
+ requestSearchModule();
+ return;
}
+
+ document.addEventListener( 'focusin', eventListener );
}
// Skins may decide to disable this behaviour or use an alternative module.
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.