foldershare-8.x-1.2/src/Utilities/LimitUtilities.php
src/Utilities/LimitUtilities.php
<?php
namespace Drupal\foldershare\Utilities;
use Drupal\Component\Utility\Bytes;
use Drupal\foldershare\Settings;
/**
* Defines utility functions to get and check memory and execution time limits.
*
* The functions in this class support runtime queries to monitor the current
* process's memory and execution time. Callers may use this to decide how
* to divide up and schedule work so that these limits are not encountered.
*
* <B>Warning:</B> This class is strictly internal to the FolderShare
* module. The class's existance, name, and content may change from
* release to release without any promise of backwards compatability.
*
* @ingroup foldershare
*/
final class LimitUtilities {
/*---------------------------------------------------------------------
*
* Functions - memory use.
*
*---------------------------------------------------------------------*/
/**
* Returns TRUE if this process is above the soft memory use limit.
*
* PHP's configuration defines a hard memory use limit. Processes that
* reach this limit are automatically aborted. This will interrupt any
* work being done and can leave operations and database state in an
* indeterminate state.
*
* To avoid hitting the hard memory use limit, this module defines a
* "soft memory use limit" as a percentage of the hard limit. The percentage
* is a configuration parameter for the module and defaults to 80%.
* Code that reaches this limit should find a way to gracefully end work
* and postpone further work until another process run. If they do not,
* they risk being aborted abruptly by PHP.
*
* This function queries the current process memory use and returns TRUE
* if that usage is above the soft limit.
*
* If PHP's configured memory limit is (-1), for unlimited memory use,
* this method always returns FALSE. However, it is not recommended practice
* to configure a site's PHP interpreter without a memory limit.
*
* @return bool
* Returns TRUE if current memory use has exceeded the memory
* use considered safe for this process.
*
* @see ::getMemoryUseLimit()
* @see ::getPhpMemoryUseLimit()
* @see \Drupal\foldershare\Settings::getMemoryUseLimitPercentage()
*/
public static function aboveMemoryUseLimit() {
// Get the current soft memory use limit.
$limit = self::getMemoryUseLimit();
if ($limit === (-1) || memory_get_usage() <= $limit) {
return FALSE;
}
return TRUE;
}
/**
* Returns the configured PHP hard memory limit.
*
* The returned value is parsed from PHP's 'memory_limit' directive,
* which is a string number that may include 'K', 'M', and 'G' suffixes
* to indicate kilobytes, megabytes, or gigabytes. A typical value is 128M.
*
* Processes that use more than this hard limit will be abruptly aborted by
* the PHP interpreter.
*
* A return value of (-1) indicates that there is no memory limit. However,
* it is not recommended practice to configure a site's PHP interpreter
* without a memory limit.
*
* @return int
* Returns PHP's configured hard memory use limit, or (-1) if there is
* no limit.
*
* @see ::aboveMemoryUseLimit()
* @see ::getMemoryUseLimit()
*/
public static function getPhpMemoryLimit() {
// Get the memory limit string.
$memoryLimit = ini_get('memory_limit');
if ($memoryLimit === FALSE) {
// The memory limit directive is not available? Assume unlimited.
return (-1);
}
if (empty($memoryLimit) === TRUE) {
// The memory limit was set to an empty string. Assume unlimited.
return (-1);
}
if ($memoryLimit < 0) {
// The memory limit was set to (-1) = unlimited, or some other
// negative value that we'll treat as (-1).
return (-1);
}
return Bytes::toInt($memoryLimit);
}
/**
* Returns the soft memory use limit set for this process.
*
* The returned value is a soft limit that is less than PHP's hard
* memory use limit. The soft limit value is computed by multiplying
* PHP's limit by a percentage less than 100% that is configured in
* this module's settings. A typical value is 80%.
*
* Unlike a hard limit, a soft limit is not monitored by the PHP interpreter.
* Passing the limit will not cause the process to be aborted.
* Instead, code may monitor memory use and check the soft limit to
* decide when to gracefully stop and schedule further work to be done by
* anothe rprocess.
*
* If PHP's configured memory limit is (-1), for unlimited memory use,
* this method returns (-1).
*
* @return int
* Returns the memory use limit for this process, or (-1) if
* there is no limit.
*
* @see ::aboveMemoryUseLimit()
* @see ::getPhpMemoryUseLimit()
* @see \Drupal\foldershare\Settings::getMemoryUseLimitPercentage()
*/
public static function getMemoryUseLimit() {
// Cache the soft memory use limit since it does not change during
// execution of a process. This avoids re-parsing the PHP memory limit,
// getting the module's configured limit percentage, etc.
static $memoryUseLimit = 0;
if ($memoryUseLimit === 0) {
// Get, parse, and return PHP's configured memory limit. A (-1)
// means there is no limit.
$memoryUseLimit = self::getPhpMemoryLimit();
if ($memoryUseLimit !== (-1)) {
// Calculate the module's own limit below PHP's based upon a
// memory use limit percentage.
$memoryUseLimit = (int) ($memoryUseLimit *
Settings::getMemoryUseLimitPercentage());
if ($memoryUseLimit === 0) {
$memoryUseLimit = (-1);
}
}
}
return $memoryUseLimit;
}
/*---------------------------------------------------------------------
*
* Functions - execution time.
*
*---------------------------------------------------------------------*/
/**
* Returns TRUE if this process is above the soft execution time limit.
*
* PHP's configuration defines a hard execution time limit. Processes that
* reach this limit are automatically aborted. This will interrupt any
* work being done and can leave operations and database state in an
* indetermine state.
*
* To avoid hitting the hard execution time limit, this module defines a
* "soft execution time limit", expressed as a percentage of the hard limit.
* typical percentage is 80%. Code that reaches this limit should find a
* way to gracefully end work and postpone further work until another
* process run. If they do not, they risk being aborted abruptly by PHP.
*
* This function queries the current process execution time and returns
* TRUE if that time is above the soft limit.
*
* If PHP's configured execution time limit is 0, for unlimited time,
* this method always returns FALSE.
*
* @return bool
* Returns TRUE if current exeuction time has exceeded the
* execution time considered safe for this process.
*
* @see ::aboveResponseExecutionTimeLimit()
* @see ::getExecutionTimeLimit()
* @see ::getPhpExecutionTimeLimit()
* @see \Drupal\foldershare\Settings::getExecutionTimeLimitPercentage()
*/
public static function aboveExecutionTimeLimit() {
$limit = self::getExecutionTimeLimit();
if ($limit <= 0) {
return FALSE;
}
$elapsedTime = time() - (int) $_SERVER['REQUEST_TIME'];
return ($elapsedTime > $limit);
}
/**
* Returns TRUE if this process is above the responsiveness time limit.
*
* PHP's configuration defines a hard execution time limit. Processes that
* reach this limit are automatically aborted. This will interrupt any
* work being done and can leave operations and database state in an
* indetermine state.
*
* A typical PHP configuration uses a 30 second execution time limit.
* However, this is far too long to make a user wait for a response.
* Responsive sites aim at response times of 5 seconds or less.
*
* To avoid hitting the hard execution time limit, or exceeding a reasonable
* responsiveness time limit, this module defines two "soft execution time
* limits". The first is expressed as a percentage of the hard limit. The
* second is a maximum time, in seconds, considered reasonable for
* responsiveness. A typical percentage is 80%, while a typical responsiveness
* limit is 5 seconds. Code that reaches either limit should find a way to
* gracefully end work and postpone further work until another process run.
* If they do not, they risk a sluggish response to the user or being
* aborted abruptly by PHP.
*
* This function queries the current process execution time and returns
* TRUE if that time is above either the soft limit or the responsiveness
* limit, whichever is less.
*
* If PHP's configured execution limit is (-1), for unlimited run time,
* this method still checks the responsiveness limit.
*
* @return bool
* Returns TRUE if current exeuction time has exceeded the execution time
* limit considered safe for this process, or the responsiveness limit
* recommended for responsive sites.
*
* @see ::getExecutionTimeLimit()
* @see ::aboveExecutionTimeLimit()
* @see \Drupal\foldershare\Settings::getResponseExecutionTimeLimit()
*/
public static function aboveResponseExecutionTimeLimit() {
// Get the current soft execution time limit and responsiveness limit.
$limit = Settings::getResponseExecutionTimeLimit();
$maxLimit = self::getExecutionTimeLimit();
// If the maximum execution time limit is actually shorter than the
// responsiveness limit (which is odd), then use it as the limit.
if ($maxLimit > 0 && $limit > $maxLimit) {
$limit = $maxLimit;
}
$elapsedTime = time() - (int) $_SERVER['REQUEST_TIME'];
return ($elapsedTime > $limit);
}
/**
* Returns the configured PHP hard execution time limit.
*
* The returned value is parsed from PHP's 'max_execution_time' directive,
* which is a time in seconds. A typical value is 30 seconds.
*
* Processes that use more than this hard limit will be abruptly aborted by
* the PHP interpreter.
*
* A return value of 0 indicates that there is no execution time limit.
* This is common for code invoked from the command line, including by
* drush.
*
* @return int
* Returns PHP's configured hard execution time limit, or 0 if there is
* no limit.
*
* @see ::aboveExecutionTimeLimit()
* @see ::getExecutionTimeLimit()
*/
public static function getPhpExecutionTimeLimit() {
// Get the limit string.
$executionTimeLimit = ini_get('max_execution_time');
if ($executionTimeLimit === FALSE) {
// The execution time limit directive is not available? Assume unlimited.
return 0;
}
$executionTimeLimit = (int) $executionTimeLimit;
return ($executionTimeLimit < 0) ? 0 : $executionTimeLimit;
}
/**
* Returns the soft execution time limit set for this process.
*
* The returned value is a soft limit that is less than PHP's hard
* execution time limit. The soft limit value is computed by multiplying
* PHP's limit by a percentage less than 100% that is configured in
* the module's settings. A typical value is 80%.
*
* Unlike a hard limit, a soft limit is not monitored by the PHP interpreter
* and passing the limit will not cause the process to be aborted.
* Instead, code may monitor execution time and check the soft limit to
* decide when to gracefully stop what they are doing and schedule a
* background task to finish the work.
*
* If PHP's configured memory limit is 0, for unlimited execution time,
* this method returns 0.
*
* @return int
* Returns the soft execution time limit for this process, or 0 if there
* is no limit.
*
* @see ::aboveExecutionTimeLimit()
* @see ::getPhpExecutionTimeLimit()
* @see \Drupal\foldershare\Settings::getExecutionTimeLimitPercentage()
*/
public static function getExecutionTimeLimit() {
// Cache the soft execution time limit since it does not change during
// execution of a process. This avoids re-parsing the PHP time limit,
// getting the module's configured limit percentage, etc.
static $executionTimeLimit = (-1);
if ($executionTimeLimit === (-1)) {
$executionTimeLimit = (float) self::getPhpExecutionTimeLimit() *
Settings::getExecutionTimeLimitPercentage();
}
return $executionTimeLimit;
}
}
