Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12345 anikendra 1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * Redistributions of files must retain the above copyright notice.
8
 *
9
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
10
 * @link          http://cakephp.org CakePHP(tm) Project
11
 * @since         DebugKit 1.0
12
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
13
 */
14
 
15
App::uses('String', 'Utility');
16
 
17
/**
18
 * Benchmark Shell Class
19
 *
20
 * Provides basic benchmarking of application requests
21
 * functionally similar to Apache AB
22
 *
23
 * @since         DebugKit 1.0
24
 * @todo Print/export time detail information
25
 * @todo Export/graphing of data to .dot format for graphviz visualization
26
 * @todo Make calculated results round to leading significant digit position of std dev.
27
 */
28
class BenchmarkShell extends Shell {
29
 
30
/**
31
 * Main execution of shell
32
 *
33
 * @return void
34
 */
35
	public function main() {
36
		$url = $this->args[0];
37
		$defaults = array('t' => 100, 'n' => 10);
38
		$options = array_merge($defaults, $this->params);
39
		$times = array();
40
 
41
		$this->out(String::insert(__d('debug_kit', '-> Testing :url'), compact('url')));
42
		$this->out("");
43
		for ($i = 0; $i < $options['n']; $i++) {
44
			if (floor($options['t'] - array_sum($times)) <= 0 || $options['n'] <= 1) {
45
				break;
46
			}
47
 
48
			$start = microtime(true);
49
			file_get_contents($url);
50
			$stop = microtime(true);
51
 
52
			$times[] = $stop - $start;
53
		}
54
		$this->_results($times);
55
	}
56
 
57
/**
58
 * Prints calculated results
59
 *
60
 * @param array $times Array of time values
61
 * @return void
62
 */
63
	protected function _results($times) {
64
		$duration = array_sum($times);
65
		$requests = count($times);
66
 
67
		$this->out(String::insert(__d('debug_kit', 'Total Requests made: :requests'), compact('requests')));
68
		$this->out(String::insert(__d('debug_kit', 'Total Time elapsed: :duration (seconds)'), compact('duration')));
69
 
70
		$this->out("");
71
 
72
		$this->out(String::insert(__d('debug_kit', 'Requests/Second: :rps req/sec'), array(
73
				'rps' => round($requests / $duration, 3)
74
		)));
75
 
76
		$this->out(String::insert(__d('debug_kit', 'Average request time: :average-time seconds'), array(
77
				'average-time' => round($duration / $requests, 3)
78
		)));
79
 
80
		$this->out(String::insert(__d('debug_kit', 'Standard deviation of average request time: :std-dev'), array(
81
				'std-dev' => round($this->_deviation($times, true), 3)
82
		)));
83
 
84
		$this->out(String::insert(__d('debug_kit', 'Longest/shortest request: :longest sec/:shortest sec'), array(
85
				'longest' => round(max($times), 3),
86
				'shortest' => round(min($times), 3)
87
		)));
88
 
89
		$this->out("");
90
	}
91
 
92
/**
93
 * One-pass, numerically stable calculation of population variance.
94
 *
95
 * Donald E. Knuth (1998).
96
 * The Art of Computer Programming, volume 2: Seminumerical Algorithms, 3rd edn.,
97
 * p. 232. Boston: Addison-Wesley.
98
 *
99
 * @param array $times Array of values
100
 * @param boolean $sample If true, calculates an unbiased estimate of the population
101
 * 						  variance from a finite sample.
102
 * @return float Variance
103
 */
104
	protected function _variance($times, $sample = true) {
105
		$n = $mean = $M2 = 0;
106
 
107
		foreach ($times as $time) {
108
			$n += 1;
109
			$delta = $time - $mean;
110
			$mean = $mean + $delta / $n;
111
			$M2 = $M2 + $delta * ($time - $mean);
112
		}
113
 
114
		if ($sample) {
115
			$n -= 1;
116
		}
117
 
118
		return $M2 / $n;
119
	}
120
 
121
/**
122
 * Calculate the standard deviation.
123
 *
124
 * @param array $times Array of values
125
 * @param boolean $sample
126
 * @return float Standard deviation
127
 */
128
	protected function _deviation($times, $sample = true) {
129
		return sqrt($this->_variance($times, $sample));
130
	}
131
 
132
	public function getOptionParser() {
133
		$parser = parent::getOptionParser();
134
		$parser->description(__d('debug_kit',
135
			'Allows you to obtain some rough benchmarking statistics' .
136
			'about a fully qualified URL.'
137
		))
138
		->addArgument('url', array(
139
			'help' => __d('debug_kit', 'The URL to request.'),
140
			'required' => true
141
		))
142
		->addOption('n', array(
143
			'default' => 10,
144
			'help' => __d('debug_kit', 'Number of iterations to perform.')
145
		))
146
		->addOption('t', array(
147
			'default' => 100,
148
			'help' => __d('debug_kit', 'Maximum total time for all iterations, in seconds.' .
149
				'If a single iteration takes more than the timeout, only one request will be made'
150
			)
151
		))
152
		->epilog(__d('debug_kit',
153
			'Example Use: `cake benchmark --n 10 --t 100 http://localhost/testsite`. ' .
154
			'<info>Note:</info> this benchmark does not include browser render times.'
155
		));
156
		return $parser;
157
	}
158
}
159