From 2bdd56e89334d85c48753b0052b0a94689dd584b Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 25 Aug 2016 21:51:01 -0700 Subject: [PATCH] mw.loader: Make 'mwLoadEnd' less expensive with a single using() 20-30ms before this patch, ~2ms after this patch (MacBookPro, Chrome 52). The creation of 100s of Deferred objects, $.when() tracking them all, and bubbling up the completion took 20-30ms. This is quite expensive. Optimise by using a single deferred first. A module reaching state 'missing' or 'error' is very rare. Change-Id: I90eea4bfe8fe6d85c395d9d0868bbde482c4a703 --- resources/src/mediawiki/mediawiki.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/resources/src/mediawiki/mediawiki.js b/resources/src/mediawiki/mediawiki.js index af37162cbe..7ceb5fe9ee 100644 --- a/resources/src/mediawiki/mediawiki.js +++ b/resources/src/mediawiki/mediawiki.js @@ -2693,14 +2693,18 @@ var loading = $.grep( mw.loader.getModuleNames(), function ( module ) { return mw.loader.getState( module ) === 'loading'; } ); - // In order to use jQuery.when (which stops early if one of the promises got rejected) - // cast any loading failures into successes. We only need a callback, not the module. - loading = $.map( loading, function ( module ) { - return mw.loader.using( module ).then( null, function () { - return $.Deferred().resolve(); + // We only need a callback, not any actual module. First try a single using() + // for all loading modules. If one fails, fall back to tracking each module + // separately via $.when(), this is expensive. + loading = mw.loader.using( loading ).then( null, function () { + var all = $.map( loading, function ( module ) { + return mw.loader.using( module ).then( null, function () { + return $.Deferred().resolve(); + } ); } ); + return $.when.apply( $, all ); } ); - $.when.apply( $, loading ).then( function () { + loading.then( function () { mwPerformance.mark( 'mwLoadEnd' ); mw.hook( 'resourceloader.loadEnd' ).fire(); } ); -- 2.20.1