Skip to content

Commit

Permalink
API CHANGE Obeying existing memory_limit settings in increase_memory_…
Browse files Browse the repository at this point in the history
…limmit_to(). Introduced set_increase_memory_limit_max() and set_increase_time_limit_max()
  • Loading branch information
chillu committed Oct 7, 2011
1 parent 54b81a3 commit 7156383
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 4 deletions.
73 changes: 69 additions & 4 deletions core/Core.php
Expand Up @@ -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. * 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. * @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) { function increase_memory_limit_to($memoryLimit = -1) {
$curLimit = ini_get('memory_limit'); $curLimit = ini_get('memory_limit');


// Can't go higher than infinite // 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 // Increase the memory limit if it's too low
if($memoryLimit == -1 || translate_memstring($memoryLimit) > translate_memstring($curLimit)) { if($memoryLimit == -1 || translate_memstring($memoryLimit) > translate_memstring($curLimit)) {
ini_set('memory_limit', $memoryLimit); 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. * Turn a memory string, such as 512M into an actual number of bytes.
*
* @param A memory limit string, such as "64M" * @param A memory limit string, such as "64M"
*/ */
function translate_memstring($memString) { function translate_memstring($memString) {
Expand All @@ -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. * @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) { 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(!ini_get('safe_mode')) {
if(!$timeLimit) { if(!$timeLimit) {
set_time_limit(0); set_time_limit(0);
return true;
} else { } else {
$currTimeLimit = ini_get('max_execution_time'); $currTimeLimit = ini_get('max_execution_time');
// Only increase if its smaller
if($currTimeLimit && $currTimeLimit < $timeLimit) { if($currTimeLimit && $currTimeLimit < $timeLimit) {
set_time_limit($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;
}
19 changes: 19 additions & 0 deletions docs/en/topics/configuration.md
Expand Up @@ -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) 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', <value>)`
and `ini_set('max_execution_time', <value>)` in your own `_config.php`.

## See Also ## See Also


[Config Cheat sheet](http://www.ssbits.com/a-config-php-cheatsheet/) [Config Cheat sheet](http://www.ssbits.com/a-config-php-cheatsheet/)
10 changes: 10 additions & 0 deletions tests/MemoryLimitTest.php
@@ -1,4 +1,8 @@
<?php <?php
/**
* @package sapphire
* @subpackage tests
*/


class MemoryLimitTest extends SapphireTest { class MemoryLimitTest extends SapphireTest {


Expand Down Expand Up @@ -66,10 +70,16 @@ function testIncreaseTimeLimitTo() {
function setUp() { function setUp() {
$this->origMemLimit = ini_get('memory_limit'); $this->origMemLimit = ini_get('memory_limit');
$this->origTimeLimit = ini_get('max_execution_time'); $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() { function tearDown() {
ini_set('memory_limit', $this->origMemLimit); ini_set('memory_limit', $this->origMemLimit);
set_time_limit($this->origTimeLimit); set_time_limit($this->origTimeLimit);
set_increase_memory_limit_max($this->origMemLimitMax);
set_increase_time_limit_max($this->origTimeLimitMax);
} }


/** /**
Expand Down

0 comments on commit 7156383

Please sign in to comment.