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