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

https://github.com/CCI-Studios/Wee-Magazine · PHP · 194 lines · 89 code · 19 blank · 86 comment · 19 complexity · 73befe2f962db63bdf2f0cb6e914371a MD5 · raw file

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