Seb35 has uploaded a new change for review. https://gerrit.wikimedia.org/r/299418
Change subject: Added the farm in the cache path ; computed performance with a strict protocol: doc added ; removed cache parameter from publicised parameters ...................................................................... Added the farm in the cache path ; computed performance with a strict protocol: doc added ; removed cache parameter from publicised parameters Previously there was a collision in cache if two farms used a same file name: fixed. The cache parameter is no more publicised in default configuration files. The reasoning is: * the user doesn’t have to know how to configure the cache directory param, that is another thing to explain in installation, and a default setting is fine, either developer-fixed, either in the main config file * the cache directory must be known before the main config file is loaded, to cache this file * it is convenient to have a possibility to disable cache, for developers * it is convenient to have a possibility to change the cache directory (shared hosts or Windows) * no cache is not an option So removing publicity of this core config param is probably the better option: by default there is a cache in a known location, and if absolutely needed, the location can be changed or the cache disabled. --- M docs/config/LocalSettings.php M docs/config/MediaWikiFarmDirectories.php M docs/config/farms.json M docs/config/farms.php M docs/config/farms.yml M docs/configuration.rst M docs/farms-schema.json M docs/performance.rst M src/MediaWikiFarm.php 9 files changed, 128 insertions(+), 75 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MediaWikiFarm refs/changes/18/299418/1 diff --git a/docs/config/LocalSettings.php b/docs/config/LocalSettings.php index e0c6be1..58b424c 100644 --- a/docs/config/LocalSettings.php +++ b/docs/config/LocalSettings.php @@ -10,11 +10,6 @@ // There must be a file 'farms.yml' or 'farms.php' or 'farms.json' inside. $wgMediaWikiFarmConfigDir = '/etc/mediawiki'; -// Cache directory. -// This can speed up the time spend by this extension from 9ms to 2ms. Set to -// null if you want to disable the cache. -$wgMediaWikiFarmCacheDir = '/tmp/mw-cache'; - # Include the code. require "$IP/extensions/MediaWikiFarm/MediaWikiFarm.php"; diff --git a/docs/config/MediaWikiFarmDirectories.php b/docs/config/MediaWikiFarmDirectories.php index c17f08b..00db886 100644 --- a/docs/config/MediaWikiFarmDirectories.php +++ b/docs/config/MediaWikiFarmDirectories.php @@ -34,15 +34,3 @@ */ $wgMediaWikiFarmCodeDir = dirname( dirname( dirname( __FILE__ ) ) ); - -/** - * Cache directory. - * - * Type: string|null. - * - * It is recommended to set this variable to a readable directory to speed up the time spent - * by this extension from 9ms to 2ms. If you want to disable the cache, you can set this - * variable to null. - */ -$wgMediaWikiFarmCacheDir = '/tmp/mw-cache'; - diff --git a/docs/config/farms.json b/docs/config/farms.json index 9e3ad0a..fdd911b 100644 --- a/docs/config/farms.json +++ b/docs/config/farms.json @@ -1,5 +1,6 @@ { - "mywiki\\.example\\.org": { + "mywiki": { + "server": "mywiki\\.example\\.org", "suffix": "wiki", "wikiID": "mywiki", "config": [ diff --git a/docs/config/farms.php b/docs/config/farms.php index 97716d4..aa4140b 100644 --- a/docs/config/farms.php +++ b/docs/config/farms.php @@ -3,8 +3,9 @@ return array( # Placeholder configuration for a first installation as detailled in the documentation - 'mywiki\.example\.org' => array( + 'mywiki' => array( + 'server' => 'mywiki\.example\.org', 'suffix' => 'wiki', 'wikiID' => 'mywiki', 'config' => array( @@ -16,8 +17,12 @@ ); /* +return array( + # Configuration similar to the Wikimedia farm - '(?<lang>[a-z-]+)\.(?<family>[a-z]+)\.org' => array( + 'wikimedia' => array( + + 'server' => '(?<lang>[a-z-]+)\.(?<family>[a-z]+)\.org', 'variables' => array( @@ -32,10 +37,14 @@ 'versions' => 'wikiversions.json', 'data' => '/srv/data/org/$family/$lang', 'config' => array( - array( 'file' => 'org/InitialiseSettings.php', + array( 'file' => 'org/DefaultSettings.yml', 'key' => '*', ), - array( 'file' => 'org/PrivateSettings.php', + array( 'file' => 'org/Settings-$family.yml', + 'key' => '*$family', + 'default' => '$family', + ), + array( 'file' => 'org/PrivateSettings.yml', 'key' => '*', ), array( 'file' => 'org/ExecSettings.php', @@ -45,7 +54,9 @@ ), # Configuration for a small wiki farm - '(?<client>[a-z]+)-(?<wiki>[a-z]+)\.example\.com' => array( + 'com-example' => array( + + 'server' => '(?<client>[a-z]+)-(?<wiki>[a-z]+)\.example\.com', 'variables' => array( @@ -77,8 +88,10 @@ # Aliases - '(?<client>[a-z]+)_(?<wiki>[a-z]+)\.example\.com' => array( + 'com-example-redirect' => array( + 'server' => '(?<client>[a-z]+)_(?<wiki>[a-z]+)\.example\.com', 'redirect' => '$client-$wiki.example.com', ), -);*/ +); +*/ diff --git a/docs/config/farms.yml b/docs/config/farms.yml index e59b57f..301cc97 100644 --- a/docs/config/farms.yml +++ b/docs/config/farms.yml @@ -1,6 +1,7 @@ # Placeholder configuration for a first installation as detailled in the documentation -'mywiki\.example\.org': +mywiki: + server: 'mywiki\.example\.org' suffix: 'wiki' wikiID: 'mywiki' config: @@ -9,7 +10,9 @@ ## Configuration similar to the Wikimedia farm -#'(?<lang>[a-z-]+)\.(?<family>[a-z]+)\.org': +#wikimedia: +# +# server: '(?<lang>[a-z-]+)\.(?<family>[a-z]+)\.org' # # variables: # @@ -23,15 +26,20 @@ # versions: 'wikiversions.json' # data: '/srv/data/org/$family/$lang' # config: -# - file: 'org/InitialiseSettings.php' +# - file: 'org/DefaultSettings.yml' # key: '*' -# - file: 'org/PrivateSettings.php' +# - file: 'org/Settings-$family.yml' +# key: '*$family' +# default: '$family' +# - file: 'org/PrivateSettings.yml' # key: '*' # - file: 'org/ExecSettings.php' # exec: true # ## Configuration for a small wiki farm -#'(?<client>[a-z]+)-(?<wiki>[a-z]+)\.example\.com': +#com-example: +# +# server: '(?<client>[a-z]+)-(?<wiki>[a-z]+)\.example\.com' # # variables: # @@ -56,6 +64,7 @@ # ## Aliases # -#'(?<client>[a-z]+)_(?<wiki>[a-z]+)\.example\.com': +#com-example-redirect: # +# server: '(?<client>[a-z]+)_(?<wiki>[a-z]+)\.example\.com' # redirect: '$client-$wiki.example.com' diff --git a/docs/configuration.rst b/docs/configuration.rst index 22394c2..b8f38e1 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -21,7 +21,9 @@ :: # A farm similar to the Wikimedia one (except for organisation of config files) - '(?<lang>[a-z-]+)\.(?<family>[a-z]+)\.org': + wikimedia: + + server: '(?<lang>[a-z-]+)\.(?<family>[a-z]+)\.org' variables: @@ -50,14 +52,24 @@ redirect: '$lang.$family.org' -Each key is a regex of the URL of a farm, and named patterns should be used to create variables. To create an internal redirect, the only subkey must be 'redirect'. +Each key is the (arbitrary) name of a farm, and values are the specific farm configuration. -In a (non-redirect) farm, two subkeys are required, 'family' and 'wikiID', and the subkey 'config' should exist (else MediaWiki default parameters will be used). +In a (non-redirect) farm, three subkeys are required, 'server', 'family', and 'wikiID', and the subkey 'config' should exist (else MediaWiki default parameters will be used). In a redirect, there must be two subkeys: 'server' and 'redirect'. + +Server +------ + +The most important subkey is 'server': it is a regular expression of the server name/domain name. There should be only one regex, which matchs a given server name. It is recommanded to use named patterns in the regex to capture parts of the server name to construct the wikiID and suffix. + +Redirect +-------- + +To avoid configuration duplicates, it is possible to internally redirect to another farm. Obviously you should enlarge existing regexes when possible (e.g. match two TLD), but you can use these redirects to avoid overcomplicated regexes, for instance to manage exceptions to a general schema. When the 'redirect' subkey is used, there must be no other subkeys. Variables --------- -The first thing to configure is the 'variables' subkey. This must be an ordered list of dictionaries. For each declared variable, it can be checked if the pattern from the regex exists. If it doesn’t exists, the wiki doesn’t exist, and a 404 page is displayed. Else, it continues to the next variable. If there is no file written in this section, no check is done and the variable is assumed to exist. The file names can contain all variables already checked (but not the current variable). +The second thing to configure is the 'variables' subkey. This must be an ordered list of dictionaries. For each declared variable, it can be checked if the pattern from the regex exists. If it doesn’t exists, the wiki doesn’t exist, and a 404 page is displayed. Else, it continues to the next variable. If there is no file written in this section, no check is done and the variable is assumed to exist. The file names can contain all variables already checked (but not the current variable). Each of these files must contain either a list of the existing values for the given variable, either a dictionary where keys are existing values for the given variable and values are MediaWiki versions. The second form is only useful for the multiversion mode and for preparation of a transition from monoversion to multiversion mode. These files can be in any previously mentionned format (YAML, JSON, PHP) or, for simple lists, in .dblist format (each line contains only a value; format used by Wikimedia). diff --git a/docs/farms-schema.json b/docs/farms-schema.json index 50009de..c8e8c4e 100644 --- a/docs/farms-schema.json +++ b/docs/farms-schema.json @@ -4,13 +4,19 @@ "type": "object", "additionalProperties": false, "patternProperties": { - "^[a-zA-Z0-9\\[\\]\\(\\)\\\\<>.*?+_-]+$": { + "^[a-zA-Z0-9_-]+$": { "oneOf": [ { "type": "object", + "description": "Configuration of a farm.", "additionalProperties": false, - "required": ["suffix", "wikiID"], + "required": ["server", "suffix", "wikiID"], "properties": { + "server": { + "type": "string", + "description": "Regular expression of the server names.", + "pattern": "^[a-zA-Z0-9\\[\\]\\(\\)\\\\<>.*?+_-]+$" + }, "variables": { "type": "array", "description": "List of variables in the host.", @@ -86,9 +92,15 @@ }, { "type": "object", + "description": "Configuration of a redirect.", "additionalProperties": false, - "required": ["redirect"], + "required": ["server", "redirect"], "properties": { + "server": { + "type": "string", + "description": "Regular expression of the server name.", + "pattern": "^[a-zA-Z0-9\\[\\]\\(\\)\\\\<>.*?+_-]+$" + }, "redirect": { "type": "string", "description": "Internal redirect to another farm.", diff --git a/docs/performance.rst b/docs/performance.rst index 19b9a9b..fa8e91d 100644 --- a/docs/performance.rst +++ b/docs/performance.rst @@ -2,30 +2,41 @@ Performance *********** +Statistics +========== + Method -====== +------ -Added microtime(true) at the top and bottom of the file LocalSettings.php. +On a monoversion MediaWikiFarm, :code:`microtime(true)` has been added on the top and bottom of the :path:`LocalSettings.php` in the Web version (no CLI) and the difference of the two numbers is computed. -On a fresh MediaWiki installation. -The only skin installed was Vector. -No extensions were installed. +MediaWiki version is 1.27.0-alpha (Git bcafa4d), the only installed (and enabled) extension is MediaWikiFarm (Git bb677fe) and the only installed (and enabled with wfLoadSkin) skin is Vector (Git 29bde53). -The figures were obtained by loading about 15-20 times a same page, and the mean and standard deviation were estimated. -Obviously a stronger sampling protocol and computation would be better, but this only aims at giving a raw idea of the results. +Tests have been done on an Intel Core i3 (x86\_64), Linux 3.16.0-4-amd64, with PHP 7.0.4 without any cache opcache, with memcached running and configured on local host, with MySQL 5.5 Server running on local host. + +The "classical LocalSettings.php" case has been done with the same configuration extracted from MediaWikiFarm and reformatted in the classic form :code:`$wgOption = 'value';`, without the extension MediaWikiFarm enabled, and with Vector loaded with :code:`wfLoadSkin`. + +Composer was executed only with the 'require' section, except if indicated otherwise. Config files are all written in YAML. -Figures -======= +Numbers +------- -* Classical LocalSettings.php: +All numbers are in milliseconds. + +* Classical LocalSettings.php without MediaWikiFarm extension: - mean = 2.7ms std = 0.2ms - -* LocalSettings.php with only MediaWikiFarm extension without cache: - - mean = 11.6ms std = 1.0ms + mean = 3.0899 median = 2.8925 std = 0.6230 min = 2.4781 max = 4.4119 range = 1.9338 values = 50 * LocalSettings.php with only MediaWikiFarm extension with cache: - mean = 8.1ms std = 1.0ms + mean = 4.8663 median = 4.7045 std = 0.7792 min = 4.0600 max = 7.0050 range = 2.9449 values = 50 + +* LocalSettings.php with only MediaWikiFarm extension without cache, Composer without 'require-dev' section: + + mean = 13.3412 median = 12.0525 std = 2.4493 min = 11.1709 max = 22.4831 range = 11.3122 values = 50 + +* LocalSettings.php with only MediaWikiFarm extension without cache, Composer with 'require-dev' section: + + mean = 14.7820 median = 13.8605 std = 2.0367 min = 13.0639 max = 20.6609 range = 7.5970 values = 50 + diff --git a/src/MediaWikiFarm.php b/src/MediaWikiFarm.php index ee5dc06..99382df 100644 --- a/src/MediaWikiFarm.php +++ b/src/MediaWikiFarm.php @@ -30,8 +30,8 @@ /** @var string|null MediaWiki code directory, where each subdirectory is a MediaWiki installation. */ private $codeDir = null; - /** @var string|null MediaWiki cache directory. */ - private $cacheDir = null; + /** @var string|false MediaWiki cache directory. */ + private $cacheDir = '/tmp/mw-cache'; /** @var bool This object cannot be used because of an emergency error. */ public $unusable = false; @@ -92,12 +92,9 @@ global $wgMediaWikiFarmConfigDir, $wgMediaWikiFarmCodeDir, $wgMediaWikiFarmCacheDir; - if( self::$self == null ) { - - # Warning: do not use $GLOBALS['_SERVER']['HTTP_HOST']: bug with PHP7: it is not initialised in early times of a script - if( is_null( $host ) ) $host = $_SERVER['HTTP_HOST'] ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; + if( self::$self == null ) self::$self = new self( $host, $wgMediaWikiFarmConfigDir, $wgMediaWikiFarmCodeDir, $wgMediaWikiFarmCacheDir ); - } + return self::$self; } @@ -266,18 +263,25 @@ * directory or file, or unrecognized host), no exception is thrown but the property * 'unusable' becomes true. * - * @param string $host Requested host. + * @param string|null $host Requested host. * @param string $configDir Configuration directory. * @param string|null $codeDir Code directory; if null, the current MediaWiki installation is used. - * @param string|null $cacheDir Cache directory; if null, the cache is disabled. + * @param string|false|null $cacheDir Cache directory; if null, the cache is disabled. */ private function __construct( $host, $configDir, $codeDir = null, $cacheDir = null ) { + + # Default value for $host + # Warning: do not use $GLOBALS['_SERVER']['HTTP_HOST']: bug with PHP7: it is not initialised in early times of a script + if( is_null( $host ) ) $host = $_SERVER['HTTP_HOST'] ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; + + # Default value for $cacheDir + if( is_null( $cacheDir ) ) $cacheDir = '/tmp/mw-cache'; # Check parameters if( !is_string( $host ) || $host == '' || !(is_string( $configDir ) && is_dir( $configDir )) || !(is_null( $codeDir ) xor (is_string( $codeDir ) && is_dir( $codeDir ))) || - !(is_null( $cacheDir ) xor is_string( $cacheDir )) + !(is_string( $cacheDir ) xor $cacheDir === false) ) { $this->unusable = true; @@ -295,26 +299,26 @@ $this->codeDir = null; if( !is_dir( $this->cacheDir ) ) - @mkdir( $this->cacheDir ); + mkdir( $this->cacheDir ); - # Read the farm(s) configuration - if( $configs = $this->readFile( 'farms.yml', $this->configDir ) ); - elseif( $configs = $this->readFile( '/farms.json', $this->configDir ) ); - elseif( $configs = $this->readFile( '/farms.php', $this->configDir ) ); + # Read the farms configuration + if( $farms = $this->readFile( 'farms.yml', $this->configDir ) ); + elseif( $farms = $this->readFile( '/farms.json', $this->configDir ) ); + elseif( $farms = $this->readFile( '/farms.php', $this->configDir ) ); else $this->unusable = true; # Now select the right configuration amoung all farms - $this->unusable = !$this->selectFarm( $configs, $host ); + $this->unusable = !$this->selectFarm( $farms, $host ); } /** * Select the farm. * - * @param array $configs All farm configurations. + * @param array $farms All farm configurations. * @param string $host Requested host. * return bool One of the farm has been selected. */ - private function selectFarm( $configs, $host ) { + private function selectFarm( $farms, $host ) { if( $this->unusable ) return false; @@ -329,9 +333,9 @@ $this->variables = array(); # For each proposed farm, check if the host matches - foreach( $configs as $regex => $config ) { + foreach( $farms as $farm => $config ) { - if( !preg_match( '/^' . $regex . '$/i', $host, $matches ) ) + if( !preg_match( '/^' . $config['server'] . '$/i', $host, $matches ) ) continue; # Initialise variables from the host @@ -350,6 +354,14 @@ # Get the selected configuration $this->params = $config; + if( $this->cacheDir ) { + + $this->cacheDir .= '/' . $farm; + + # Create cache directory + if( !is_dir( $this->cacheDir ) ) + mkdir( $this->cacheDir ); + } return true; } @@ -834,7 +846,7 @@ } # Cached version - elseif( is_file( $this->cacheDir . '/' . $filename . '.ser' ) && @filemtime( $this->cacheDir . '/' . $filename . '.ser' ) >= @filemtime( $prefixedFile ) ) + elseif( is_string( $this->cacheDir ) && is_file( $this->cacheDir . '/' . $filename . '.ser' ) && @filemtime( $this->cacheDir . '/' . $filename . '.ser' ) >= @filemtime( $prefixedFile ) ) return $this->readFile( $filename . '.ser', $this->cacheDir ); -- To view, visit https://gerrit.wikimedia.org/r/299418 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I8d93f25bd2d275303f9f9aa9ed806f7a154d7973 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/MediaWikiFarm Gerrit-Branch: master Gerrit-Owner: Seb35 <seb35wikipe...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits