Trevor Parscal has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/168732

Change subject: Index ResourceLoader dependency lists in startup
......................................................................

Index ResourceLoader dependency lists in startup

By using the existing indexes of modules in the array being passed to 
mw.loader.register we can reduce the size of startup.js by about 6% after gzip 
(nearly 20% before) on a wiki with very few modules (such as my localhost). 
Comparing data from en.wikipedia.org shows about 9% after gzip (nearly 30% 
before).

The technique adds a function to mediawiki.js which resolves the indexes before 
registering the modules, which costs a little bit of data in that payload, but 
it's negligable (118 bytes after gzip) in comparison to the overall reduction.

Change-Id: If12991413fa6129cd20ceab0e59a3a30a4fdf5ce
---
M includes/resourceloader/ResourceLoader.php
M includes/resourceloader/ResourceLoaderStartUpModule.php
M resources/src/mediawiki/mediawiki.js
3 files changed, 72 insertions(+), 15 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/32/168732/1

diff --git a/includes/resourceloader/ResourceLoader.php 
b/includes/resourceloader/ResourceLoader.php
index 57deb00..7ed6a64 100644
--- a/includes/resourceloader/ResourceLoader.php
+++ b/includes/resourceloader/ResourceLoader.php
@@ -1205,6 +1205,24 @@
                $dependencies = null, $group = null, $source = null, $skip = 
null
        ) {
                if ( is_array( $name ) ) {
+                       // Build module name index
+                       $index = array();
+                       foreach ( $name as $i => $module ) {
+                               $index[$module[0]] = $i;
+                       }
+
+                       // Transform dependency names into indexes when 
possible, they will be resolved by
+                       // mw.loader.register on the other end
+                       foreach ( $name as &$module ) {
+                               if ( isset( $module[2] ) ) {
+                                       foreach ( $module[2] as &$dependency ) {
+                                               if ( isset( $index[$dependency] 
) ) {
+                                                       $dependency = 
$index[$dependency];
+                                               }
+                                       }
+                               }
+                       }
+
                        return Xml::encodeJsCall(
                                'mw.loader.register',
                                array( $name ),
diff --git a/includes/resourceloader/ResourceLoaderStartUpModule.php 
b/includes/resourceloader/ResourceLoaderStartUpModule.php
index ee66288..5d94b5d 100644
--- a/includes/resourceloader/ResourceLoaderStartUpModule.php
+++ b/includes/resourceloader/ResourceLoaderStartUpModule.php
@@ -147,7 +147,7 @@
        }
 
        /**
-        * Optimize the dependency tree in $this->modules and return it.
+        * Optimize the dependency tree in $this->modules.
         *
         * The optimization basically works like this:
         *      Given we have module A with the dependencies B and C
@@ -155,7 +155,7 @@
         *      Now we don't have to tell the client to explicitly fetch module
         *              C as that's already included in module B.
         *
-        * This way we can reasonably reduce the amout of module registration
+        * This way we can reasonably reduce the amount of module registration
         * data send to the client.
         *
         * @param array &$registryData Modules keyed by name with properties:
@@ -251,7 +251,7 @@
                        if ( $data['loader'] !== false ) {
                                $out .= ResourceLoader::makeCustomLoaderScript(
                                        $name,
-                                       wfTimestamp( TS_ISO_8601_BASIC, 
$data['version'] ),
+                                       intval( $data['version'] ),
                                        $data['dependencies'],
                                        $data['group'],
                                        $data['source'],
@@ -268,7 +268,7 @@
                        ) {
                                // Modules with no dependencies, group, foreign 
source or skip function;
                                // call mw.loader.register(name, timestamp)
-                               $registrations[] = array( $name, 
$data['version'] );
+                               $registrations[] = array( $name, intval( 
$data['version'] ) );
                        } elseif (
                                $data['group'] === null &&
                                $data['source'] === 'local' &&
@@ -276,7 +276,11 @@
                        ) {
                                // Modules with dependencies but no group, 
foreign source or skip function;
                                // call mw.loader.register(name, timestamp, 
dependencies)
-                               $registrations[] = array( $name, 
$data['version'], $data['dependencies'] );
+                               $registrations[] = array(
+                                       $name,
+                                       intval( $data['version'] ),
+                                       $data['dependencies']
+                               );
                        } elseif (
                                $data['source'] === 'local' &&
                                $data['skip'] === null
@@ -285,7 +289,7 @@
                                // call mw.loader.register(name, timestamp, 
dependencies, group)
                                $registrations[] = array(
                                        $name,
-                                       $data['version'],
+                                       intval( $data['version'] ),
                                        $data['dependencies'],
                                        $data['group']
                                );
@@ -294,7 +298,7 @@
                                // call mw.loader.register(name, timestamp, 
dependencies, group, source)
                                $registrations[] = array(
                                        $name,
-                                       $data['version'],
+                                       intval( $data['version'] ),
                                        $data['dependencies'],
                                        $data['group'],
                                        $data['source']
@@ -304,7 +308,7 @@
                                // call mw.loader.register(name, timestamp, 
dependencies, group, source, skip)
                                $registrations[] = array(
                                        $name,
-                                       $data['version'],
+                                       intval( $data['version'] ),
                                        $data['dependencies'],
                                        $data['group'],
                                        $data['source'],
diff --git a/resources/src/mediawiki/mediawiki.js 
b/resources/src/mediawiki/mediawiki.js
index e29c734..6097bd8 100644
--- a/resources/src/mediawiki/mediawiki.js
+++ b/resources/src/mediawiki/mediawiki.js
@@ -1354,6 +1354,35 @@
                                addScript( sourceLoadScript + '?' + $.param( 
request ) + '&*', null, async );
                        }
 
+                       /**
+                        * Resolve indexed dependencies.
+                        *
+                        * ResourceLoader uses an optimization to save space 
which replaces module names in
+                        * dependency lists with the index of that module 
within the array of module
+                        * registration data if it exists. The benefit is a 
significant reduction in the data
+                        * size of the startup module. This function changes 
those dependency lists back to
+                        * arrays of strings.
+                        *
+                        * @param {[type]} modules [description]
+                        * @return {[type]} [description]
+                        */
+                       function resolveIndexedDependencies( modules ) {
+                               var i, iLen, j, jLen, module, dependency;
+
+                               // Expand indexed dependency names
+                               for ( i = 0, iLen = modules.length; i < iLen; 
i++ ) {
+                                       module = modules[i];
+                                       if ( module[2] ) {
+                                               for ( j = 0, jLen = 
module[2].length; j < jLen; j++ ) {
+                                                       dependency = 
module[2][j];
+                                                       if ( typeof dependency 
=== 'number' ) {
+                                                               module[2][j] = 
modules[dependency][0];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
                        /* Public Members */
                        return {
                                /**
@@ -1586,7 +1615,12 @@
                                 * Register a module, letting the system know 
about it and its
                                 * properties. Startup modules contain calls to 
this function.
                                 *
-                                * @param {string} module Module name
+                                * When using multiple module registration by 
passing an array, dependencies that
+                                * are specified as references to modules 
within the array will be resolved before
+                                * the modules are registered.
+                                *
+                                * @param {string|Array} module Module name or 
array of arrays, each containing
+                                *   a list of arguments compatible with this 
method
                                 * @param {number} version Module version 
number as a timestamp (falls backs to 0)
                                 * @param {string|Array|Function} dependencies 
One string or array of strings of module
                                 *  names on which this module depends, or a 
function that returns that array.
@@ -1595,16 +1629,17 @@
                                 * @param {string} [skip=null] Script body of 
the skip function
                                 */
                                register: function ( module, version, 
dependencies, group, source, skip ) {
-                                       var m;
+                                       var i, len;
                                        // Allow multiple registration
                                        if ( typeof module === 'object' ) {
-                                               for ( m = 0; m < module.length; 
m += 1 ) {
+                                               resolveIndexedDependencies( 
module );
+                                               for ( i = 0, len = 
module.length; i < len; i++ ) {
                                                        // module is an array 
of module names
-                                                       if ( typeof module[m] 
=== 'string' ) {
-                                                               
mw.loader.register( module[m] );
+                                                       if ( typeof module[i] 
=== 'string' ) {
+                                                               
mw.loader.register( module[i] );
                                                        // module is an array 
of arrays
-                                                       } else if ( typeof 
module[m] === 'object' ) {
-                                                               
mw.loader.register.apply( mw.loader, module[m] );
+                                                       } else if ( typeof 
module[i] === 'object' ) {
+                                                               
mw.loader.register.apply( mw.loader, module[i] );
                                                        }
                                                }
                                                return;

-- 
To view, visit https://gerrit.wikimedia.org/r/168732
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If12991413fa6129cd20ceab0e59a3a30a4fdf5ce
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Trevor Parscal <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to