diff --git a/core/Core.php b/core/Core.php index 34d868fb9..de6054961 100644 --- a/core/Core.php +++ b/core/Core.php @@ -366,22 +366,55 @@ function _t($entity, $string = "", $priority = 40, $context = "") { /** * Increase the memory limit to the given level if it's currently too low. + * Only increases up to the maximum defined in {@link set_increase_memory_limit_max()}, + * and defaults to the 'memory_limit' setting in the PHP configuration. + * * @param A memory limit string, such as "64M". If omitted, unlimited memory will be set. + * @return Boolean TRUE indicates a successful change, FALSE a denied change. */ function increase_memory_limit_to($memoryLimit = -1) { $curLimit = ini_get('memory_limit'); // Can't go higher than infinite - if($curLimit == -1) return; + if($curLimit == -1 ) return true; + + // Check hard maximums + $max = get_increase_memory_limit_max(); + if($max != -1 && translate_memstring($memoryLimit) > translate_memstring($max)) return false; // Increase the memory limit if it's too low if($memoryLimit == -1 || translate_memstring($memoryLimit) > translate_memstring($curLimit)) { ini_set('memory_limit', $memoryLimit); - } + } + + return true; +} + +$_increase_memory_limit_max = ini_get('memory_limit'); + +/** + * Set the maximum allowed value for {@link increase_memory_limit_to()}. + * The same result can also be achieved through 'suhosin.memory_limit' + * if PHP is running with the Suhosin system. + * + * @param Memory limit string + */ +function set_increase_memory_limit_max($memoryLimit) { + global $_increase_memory_limit_max; + $_increase_memory_limit_max = $memoryLimit; +} + +/** + * @return Memory limit string + */ +function get_increase_memory_limit_max() { + global $_increase_memory_limit_max; + return $_increase_memory_limit_max; } /** * Turn a memory string, such as 512M into an actual number of bytes. + * * @param A memory limit string, such as "64M" */ function translate_memstring($memString) { @@ -394,18 +427,50 @@ function translate_memstring($memString) { } /** - * Increase the time limit of this script. By default, the time will be unlimited. + * Increase the time limit of this script. By default, the time will be unlimited. + * Only works if 'safe_mode' is off in the PHP configuration. + * Only values up to {@link get_increase_time_limit_max()} are allowed. + * * @param $timeLimit The time limit in seconds. If omitted, no time limit will be set. + * @return Boolean TRUE indicates a successful change, FALSE a denied change. */ function increase_time_limit_to($timeLimit = null) { + $max = get_increase_time_limit_max(); + if($max != -1 && $timeLimit > $max) return false; + if(!ini_get('safe_mode')) { if(!$timeLimit) { set_time_limit(0); + return true; } else { $currTimeLimit = ini_get('max_execution_time'); + // Only increase if its smaller if($currTimeLimit && $currTimeLimit < $timeLimit) { set_time_limit($timeLimit); - } + } + return true; } + } else { + return false; } } + +$_increase_time_limit_max = -1; + +/** + * Set the maximum allowed value for {@link increase_timeLimit_to()}; + * + * @param Int Limit in seconds + */ +function set_increase_time_limit_max($timeLimit) { + global $_increase_time_limit_max; + $_increase_time_limit_max = $timeLimit; +} + +/** + * @return Int Limit in seconds + */ +function get_increase_time_limit_max() { + global $_increase_time_limit_max; + return $_increase_time_limit_max; +} diff --git a/docs/en/topics/configuration.md b/docs/en/topics/configuration.md index 7218088ed..07124b717 100644 --- a/docs/en/topics/configuration.md +++ b/docs/en/topics/configuration.md @@ -74,6 +74,25 @@ All user-related preferences are stored as a property of the `[api:Member]`-clas See [security](/topics/security) and [permission](/reference/permission) +## Resource Usage (Memory and CPU) + +SilverStripe tries to keep its resource usage within the documented limits (see our [server requirements](../installation/server-requirements)). +These limits are defined through `memory_limit` and `max_execution_time` in the PHP configuration. +They can be overwritten through `ini_set()`, unless PHP is running with the [Suhoshin Patches](http://www.hardened-php.net/) +or in "[safe mode](http://php.net/manual/en/features.safe-mode.php)". +Most shared hosting providers will have maximum values that can't be altered. + +For certain tasks like synchronizing a large `assets/` folder with all file and folder entries in the database, +more resources are required temporarily. In general, we recommend running resource intensive tasks +through the [commandline](../topics/commandline), where configuration defaults for these settings are higher or even unlimited. + +SilverStripe can request more resources through `increase_memory_limit_to()` and `increase_time_limit_to()`. +If you are concerned about resource usage on a dedicated server (without restrictions imposed through shared hosting providers), you can set a hard limit to these increases through +`set_increase_memory_limit_max()` and `set_increase_time_limit_max()`. +These values will just be used for specific scripts (e.g. `[api:Filesystem::sync()]`), +to raise the limits for all executed scripts please use `ini_set('memory_limit', )` +and `ini_set('max_execution_time', )` in your own `_config.php`. + ## See Also [Config Cheat sheet](http://www.ssbits.com/a-config-php-cheatsheet/) \ No newline at end of file diff --git a/tests/MemoryLimitTest.php b/tests/MemoryLimitTest.php index 6ae15d27c..d22ef05b0 100644 --- a/tests/MemoryLimitTest.php +++ b/tests/MemoryLimitTest.php @@ -1,4 +1,8 @@ origMemLimit = ini_get('memory_limit'); $this->origTimeLimit = ini_get('max_execution_time'); + $this->origMemLimitMax = get_increase_memory_limit_max(); + $this->origTimeLimitMax = get_increase_time_limit_max(); + set_increase_memory_limit_max(-1); + set_increase_time_limit_max(-1); } function tearDown() { ini_set('memory_limit', $this->origMemLimit); set_time_limit($this->origTimeLimit); + set_increase_memory_limit_max($this->origMemLimitMax); + set_increase_time_limit_max($this->origTimeLimitMax); } /**