PageRenderTime 45ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/system/classes/kohana/profiler.php

https://bitbucket.org/alvinpd/monsterninja
PHP | 377 lines | 182 code | 57 blank | 138 comment | 14 complexity | 02afe63d1af1ee7d6ba373763d99c3d3 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Provides simple benchmarking and profiling. To display the statistics that
  4. * have been collected, load the `profiler/stats` [View]:
  5. *
  6. * echo View::factory('profiler/stats');
  7. *
  8. * @package Kohana
  9. * @category Helpers
  10. * @author Kohana Team
  11. * @copyright (c) 2009-2010 Kohana Team
  12. * @license http://kohanaphp.com/license
  13. */
  14. class Kohana_Profiler {
  15. /**
  16. * @var integer maximium number of application stats to keep
  17. */
  18. public static $rollover = 1000;
  19. // Collected benchmarks
  20. protected static $_marks = array();
  21. /**
  22. * Starts a new benchmark and returns a unique token. The returned token
  23. * _must_ be used when stopping the benchmark.
  24. *
  25. * $token = Profiler::start('test', 'profiler');
  26. *
  27. * @param string group name
  28. * @param string benchmark name
  29. * @return string
  30. */
  31. public static function start($group, $name)
  32. {
  33. static $counter = 0;
  34. // Create a unique token based on the counter
  35. $token = 'kp/'.base_convert($counter++, 10, 32);
  36. Profiler::$_marks[$token] = array
  37. (
  38. 'group' => strtolower($group),
  39. 'name' => (string) $name,
  40. // Start the benchmark
  41. 'start_time' => microtime(TRUE),
  42. 'start_memory' => memory_get_usage(),
  43. // Set the stop keys without values
  44. 'stop_time' => FALSE,
  45. 'stop_memory' => FALSE,
  46. );
  47. return $token;
  48. }
  49. /**
  50. * Stops a benchmark.
  51. *
  52. * Profiler::stop($token);
  53. *
  54. * @param string token
  55. * @return void
  56. */
  57. public static function stop($token)
  58. {
  59. // Stop the benchmark
  60. Profiler::$_marks[$token]['stop_time'] = microtime(TRUE);
  61. Profiler::$_marks[$token]['stop_memory'] = memory_get_usage();
  62. }
  63. /**
  64. * Deletes a benchmark. If an error occurs during the benchmark, it is
  65. * recommended to delete the benchmark to prevent statistics from being
  66. * adversely affected.
  67. *
  68. * Profiler::delete($token);
  69. *
  70. * @param string token
  71. * @return void
  72. */
  73. public static function delete($token)
  74. {
  75. // Remove the benchmark
  76. unset(Profiler::$_marks[$token]);
  77. }
  78. /**
  79. * Returns all the benchmark tokens by group and name as an array.
  80. *
  81. * $groups = Profiler::groups();
  82. *
  83. * @return array
  84. */
  85. public static function groups()
  86. {
  87. $groups = array();
  88. foreach (Profiler::$_marks as $token => $mark)
  89. {
  90. // Sort the tokens by the group and name
  91. $groups[$mark['group']][$mark['name']][] = $token;
  92. }
  93. return $groups;
  94. }
  95. /**
  96. * Gets the min, max, average and total of a set of tokens as an array.
  97. *
  98. * $stats = Profiler::stats($tokens);
  99. *
  100. * @param array profiler tokens
  101. * @return array min, max, average, total
  102. * @uses Profiler::total
  103. */
  104. public static function stats(array $tokens)
  105. {
  106. // Min and max are unknown by default
  107. $min = $max = array(
  108. 'time' => NULL,
  109. 'memory' => NULL);
  110. // Total values are always integers
  111. $total = array(
  112. 'time' => 0,
  113. 'memory' => 0);
  114. foreach ($tokens as $token)
  115. {
  116. // Get the total time and memory for this benchmark
  117. list($time, $memory) = Profiler::total($token);
  118. if ($max['time'] === NULL OR $time > $max['time'])
  119. {
  120. // Set the maximum time
  121. $max['time'] = $time;
  122. }
  123. if ($min['time'] === NULL OR $time < $min['time'])
  124. {
  125. // Set the minimum time
  126. $min['time'] = $time;
  127. }
  128. // Increase the total time
  129. $total['time'] += $time;
  130. if ($max['memory'] === NULL OR $memory > $max['memory'])
  131. {
  132. // Set the maximum memory
  133. $max['memory'] = $memory;
  134. }
  135. if ($min['memory'] === NULL OR $memory < $min['memory'])
  136. {
  137. // Set the minimum memory
  138. $min['memory'] = $memory;
  139. }
  140. // Increase the total memory
  141. $total['memory'] += $memory;
  142. }
  143. // Determine the number of tokens
  144. $count = count($tokens);
  145. // Determine the averages
  146. $average = array(
  147. 'time' => $total['time'] / $count,
  148. 'memory' => $total['memory'] / $count);
  149. return array(
  150. 'min' => $min,
  151. 'max' => $max,
  152. 'total' => $total,
  153. 'average' => $average);
  154. }
  155. /**
  156. * Gets the min, max, average and total of profiler groups as an array.
  157. *
  158. * $stats = Profiler::group_stats('test');
  159. *
  160. * @param mixed single group name string, or array with group names; all groups by default
  161. * @return array min, max, average, total
  162. * @uses Profiler::groups
  163. * @uses Profiler::stats
  164. */
  165. public static function group_stats($groups = NULL)
  166. {
  167. // Which groups do we need to calculate stats for?
  168. $groups = ($groups === NULL)
  169. ? Profiler::groups()
  170. : array_intersect_key(Profiler::groups(), array_flip((array) $groups));
  171. foreach ($groups as $group => $names)
  172. {
  173. foreach ($names as $name => $tokens)
  174. {
  175. // Store the stats for each subgroup.
  176. // We only need the values for "total".
  177. $_stats = Profiler::stats($tokens);
  178. $stats[$group][$name] = $_stats['total'];
  179. }
  180. }
  181. // Group stats
  182. $groups = array();
  183. foreach ($stats as $group => $names)
  184. {
  185. // Min and max are unknown by default
  186. $groups[$group]['min'] = $groups[$group]['max'] = array(
  187. 'time' => NULL,
  188. 'memory' => NULL);
  189. // Total values are always integers
  190. $groups[$group]['total'] = array(
  191. 'time' => 0,
  192. 'memory' => 0);
  193. foreach ($names as $total)
  194. {
  195. if ( ! isset($groups[$group]['min']['time']) OR $groups[$group]['min']['time'] > $total['time'])
  196. {
  197. // Set the minimum time
  198. $groups[$group]['min']['time'] = $total['time'];
  199. }
  200. if ( ! isset($groups[$group]['min']['memory']) OR $groups[$group]['min']['memory'] > $total['memory'])
  201. {
  202. // Set the minimum memory
  203. $groups[$group]['min']['memory'] = $total['memory'];
  204. }
  205. if ( ! isset($groups[$group]['max']['time']) OR $groups[$group]['max']['time'] < $total['time'])
  206. {
  207. // Set the maximum time
  208. $groups[$group]['max']['time'] = $total['time'];
  209. }
  210. if ( ! isset($groups[$group]['max']['memory']) OR $groups[$group]['max']['memory'] < $total['memory'])
  211. {
  212. // Set the maximum memory
  213. $groups[$group]['max']['memory'] = $total['memory'];
  214. }
  215. // Increase the total time and memory
  216. $groups[$group]['total']['time'] += $total['time'];
  217. $groups[$group]['total']['memory'] += $total['memory'];
  218. }
  219. // Determine the number of names (subgroups)
  220. $count = count($names);
  221. // Determine the averages
  222. $groups[$group]['average']['time'] = $groups[$group]['total']['time'] / $count;
  223. $groups[$group]['average']['memory'] = $groups[$group]['total']['memory'] / $count;
  224. }
  225. return $groups;
  226. }
  227. /**
  228. * Gets the total execution time and memory usage of a benchmark as a list.
  229. *
  230. * list($time, $memory) = Profiler::total($token);
  231. *
  232. * @param string token
  233. * @return array execution time, memory
  234. */
  235. public static function total($token)
  236. {
  237. // Import the benchmark data
  238. $mark = Profiler::$_marks[$token];
  239. if ($mark['stop_time'] === FALSE)
  240. {
  241. // The benchmark has not been stopped yet
  242. $mark['stop_time'] = microtime(TRUE);
  243. $mark['stop_memory'] = memory_get_usage();
  244. }
  245. return array
  246. (
  247. // Total time in seconds
  248. $mark['stop_time'] - $mark['start_time'],
  249. // Amount of memory in bytes
  250. $mark['stop_memory'] - $mark['start_memory'],
  251. );
  252. }
  253. /**
  254. * Gets the total application run time and memory usage. Caches the result
  255. * so that it can be compared between requests.
  256. *
  257. * list($time, $memory) = Profiler::application();
  258. *
  259. * @return array execution time, memory
  260. * @uses Kohana::cache
  261. */
  262. public static function application()
  263. {
  264. // Load the stats from cache, which is valid for 1 day
  265. $stats = Kohana::cache('profiler_application_stats', NULL, 3600 * 24);
  266. if ( ! is_array($stats) OR $stats['count'] > Profiler::$rollover)
  267. {
  268. // Initialize the stats array
  269. $stats = array(
  270. 'min' => array(
  271. 'time' => NULL,
  272. 'memory' => NULL),
  273. 'max' => array(
  274. 'time' => NULL,
  275. 'memory' => NULL),
  276. 'total' => array(
  277. 'time' => NULL,
  278. 'memory' => NULL),
  279. 'count' => 0);
  280. }
  281. // Get the application run time
  282. $time = microtime(TRUE) - KOHANA_START_TIME;
  283. // Get the total memory usage
  284. $memory = memory_get_usage() - KOHANA_START_MEMORY;
  285. // Calculate max time
  286. if ($stats['max']['time'] === NULL OR $time > $stats['max']['time'])
  287. $stats['max']['time'] = $time;
  288. // Calculate min time
  289. if ($stats['min']['time'] === NULL OR $time < $stats['min']['time'])
  290. $stats['min']['time'] = $time;
  291. // Add to total time
  292. $stats['total']['time'] += $time;
  293. // Calculate max memory
  294. if ($stats['max']['memory'] === NULL OR $memory > $stats['max']['memory'])
  295. $stats['max']['memory'] = $memory;
  296. // Calculate min memory
  297. if ($stats['min']['memory'] === NULL OR $memory < $stats['min']['memory'])
  298. $stats['min']['memory'] = $memory;
  299. // Add to total memory
  300. $stats['total']['memory'] += $memory;
  301. // Another mark has been added to the stats
  302. $stats['count']++;
  303. // Determine the averages
  304. $stats['average'] = array(
  305. 'time' => $stats['total']['time'] / $stats['count'],
  306. 'memory' => $stats['total']['memory'] / $stats['count']);
  307. // Cache the new stats
  308. Kohana::cache('profiler_application_stats', $stats);
  309. // Set the current application execution time and memory
  310. // Do NOT cache these, they are specific to the current request only
  311. $stats['current']['time'] = $time;
  312. $stats['current']['memory'] = $memory;
  313. // Return the total application run time and memory usage
  314. return $stats;
  315. }
  316. final private function __construct()
  317. {
  318. // This is a static class
  319. }
  320. } // End Profiler