/administrator/components/com_akeeba/akeeba/core/timer.php

https://bitbucket.org/dreamriks/gift · PHP · 190 lines · 110 code · 21 blank · 59 comment · 24 complexity · a6904de59bcc8743bab473670fbcab17 MD5 · raw file

  1. <?php
  2. /**
  3. * Akeeba Engine
  4. * The modular PHP5 site backup engine
  5. * @copyright Copyright (c)2009-2011 Nicholas K. Dionysopoulos
  6. * @license GNU GPL version 3 or, at your option, any later version
  7. * @package akeebaengine
  8. * @version $Id: timer.php 409 2011-01-24 09:30:22Z nikosdion $
  9. */
  10. // Protection against direct access
  11. defined('AKEEBAENGINE') or die('Restricted access');
  12. /**
  13. * Timer class
  14. */
  15. class AECoreTimer extends AEAbstractObject
  16. {
  17. /** @var int Maximum execution time allowance per step */
  18. private $max_exec_time = null;
  19. /** @var int Timestamp of execution start */
  20. private $start_time = null;
  21. /**
  22. * Public constructor, creates the timer object and calculates the execution time limits
  23. * @return AECoreTimer
  24. */
  25. public function __construct()
  26. {
  27. parent::__construct();
  28. // Initialize start time
  29. $this->start_time = $this->microtime_float();
  30. // Get configured max time per step and bias
  31. $configuration =& AEFactory::getConfiguration();
  32. $config_max_exec_time = $configuration->get('akeeba.tuning.max_exec_time', 14);
  33. $bias = $configuration->get('akeeba.tuning.run_time_bias', 75)/100;
  34. // Get PHP's maximum execution time (our upper limit)
  35. if(@function_exists('ini_get'))
  36. {
  37. $php_max_exec_time = @ini_get("maximum_execution_time");
  38. if ( (!is_numeric($php_max_exec_time)) || ($php_max_exec_time == 0) ) {
  39. // If we have no time limit, set a hard limit of about 10 seconds
  40. // (safe for Apache and IIS timeouts, verbose enough for users)
  41. $php_max_exec_time = 14;
  42. }
  43. }
  44. else
  45. {
  46. // If ini_get is not available, use a rough default
  47. $php_max_exec_time = 14;
  48. }
  49. // Apply an arbitrary correction to counter CMS load time
  50. $php_max_exec_time--;
  51. // Apply bias
  52. $php_max_exec_time = $php_max_exec_time * $bias;
  53. $config_max_exec_time = $config_max_exec_time * $bias;
  54. // Use the most appropriate time limit value
  55. if( $config_max_exec_time > $php_max_exec_time )
  56. {
  57. $this->max_exec_time = $php_max_exec_time;
  58. }
  59. else
  60. {
  61. $this->max_exec_time = $config_max_exec_time;
  62. }
  63. }
  64. /**
  65. * Wake-up function to reset internal timer when we get unserialized
  66. */
  67. public function __wakeup()
  68. {
  69. // Re-initialize start time on wake-up
  70. $this->start_time = $this->microtime_float();
  71. }
  72. /**
  73. * Gets the number of seconds left, before we hit the "must break" threshold
  74. * @return float
  75. */
  76. public function getTimeLeft()
  77. {
  78. return $this->max_exec_time - $this->getRunningTime();
  79. }
  80. /**
  81. * Gets the time elapsed since object creation/unserialization, effectively how
  82. * long Akeeba Engine has been processing data
  83. * @return float
  84. */
  85. public function getRunningTime()
  86. {
  87. return $this->microtime_float() - $this->start_time;
  88. }
  89. /**
  90. * Returns the current timestampt in decimal seconds
  91. */
  92. private function microtime_float()
  93. {
  94. list($usec, $sec) = explode(" ", microtime());
  95. return ((float)$usec + (float)$sec);
  96. }
  97. /**
  98. * Enforce the minimum execution time
  99. * @param bool $log Should I log what I'm doing? Default is true.
  100. */
  101. public function enforce_min_exec_time($log = true)
  102. {
  103. // Try to get a sane value for PHP's maximum_execution_time INI parameter
  104. if(@function_exists('ini_get'))
  105. {
  106. $php_max_exec = @ini_get("maximum_execution_time");
  107. }
  108. else
  109. {
  110. $php_max_exec = 10;
  111. }
  112. if ( ($php_max_exec == "") || ($php_max_exec == 0) ) {
  113. $php_max_exec = 10;
  114. }
  115. // Decrease $php_max_exec time by 500 msec we need (approx.) to tear down
  116. // the application, as well as another 500msec added for rounding
  117. // error purposes. Also make sure this is never gonna be less than 0.
  118. $php_max_exec = max($php_max_exec * 1000 - 1000, 0);
  119. // Get the "minimum execution time per step" Akeeba Backup configuration variable
  120. $configuration =& AEFactory::getConfiguration();
  121. $minexectime = $configuration->get('akeeba.tuning.min_exec_time',0);
  122. if(!is_numeric($minexectime)) $minexectime = 0;
  123. // Make sure we are not over PHP's time limit!
  124. if($minexectime > $php_max_exec) $minexectime = $php_max_exec;
  125. // Get current running time
  126. $elapsed_time = $this->getRunningTime() * 1000;
  127. // Only run a sleep delay if we haven't reached the minexectime execution time
  128. if( ($minexectime > $elapsed_time) && ($elapsed_time > 0) )
  129. {
  130. $sleep_msec = $minexectime - $elapsed_time;
  131. if(function_exists('usleep'))
  132. {
  133. if($log) AEUtilLogger::WriteLog( _AE_LOG_DEBUG, "Sleeping for $sleep_msec msec, using usleep()" );
  134. usleep(1000 * $sleep_msec);
  135. }
  136. elseif(function_exists('time_nanosleep'))
  137. {
  138. if($log) AEUtilLogger::WriteLog( _AE_LOG_DEBUG, "Sleeping for $sleep_msec msec, using time_nanosleep()" );
  139. $sleep_sec = floor($sleep_msec / 1000);
  140. $sleep_nsec = 1000000 * ($sleep_msec - ($sleep_sec * 1000));
  141. time_nanosleep($sleep_sec, $sleep_nsec);
  142. }
  143. elseif(function_exists('time_sleep_until'))
  144. {
  145. if($log) AEUtilLogger::WriteLog( _AE_LOG_DEBUG, "Sleeping for $sleep_msec msec, using time_sleep_until()" );
  146. $until_timestamp = time() + $sleep_msec / 1000;
  147. time_sleep_until($until_timestamp);
  148. }
  149. elseif(function_exists('sleep'))
  150. {
  151. $sleep_sec = ceil($sleep_msec/1000);
  152. if($log) AEUtilLogger::WriteLog( _AE_LOG_DEBUG, "Sleeping for $sleep_sec seconds, using sleep()" );
  153. sleep( $sleep_sec );
  154. }
  155. }
  156. elseif( $elapsed_time > 0 )
  157. {
  158. // No sleep required, even if user configured us to be able to do so.
  159. if($log) AEUtilLogger::WriteLog( _AE_LOG_DEBUG, "No need to sleep; execution time: $elapsed_time msec; min. exec. time: $minexectime msec" );
  160. }
  161. }
  162. /**
  163. * Reset the timer. It should only be used in CLI mode!
  164. */
  165. public function resetTime()
  166. {
  167. $this->start_time = $this->microtime_float();
  168. }
  169. }