4 require_once 'Pman/Core/Cli.php';
5 class Pman_Admin_Tools_LoadTest extends Pman_Core_Cli
8 static $cli_desc = "Load testing for a domain";
10 static $cli_opts = array(
12 'per_second' => array(
13 'desc' => 'Request per second (default 1)',
21 'desc' => 'Timeout in seconds',
27 'desc' => 'Total tests (20)',
34 // try and do some load testing..
35 var $total = 20; // total number of tests to run.
36 var $timeout = 5; // for each request.
37 var $per_second = 2; // how many per second.
38 var $host = 'www-new.regulationasia.com';
39 var $url = 'https://sg2-web.regulationasia.com/';
41 var $cmd = ""; // filled in by initCmd
46 function get($r,$opts=array())
49 // print_R($opts);exit;
50 foreach($opts as $k=>$v) {
57 Request Per Second: {$this->per_second}
58 No. Requests : {$this->total}
59 Timeout: {$this->timeout}
70 $ps = $this->poolsize();
72 if ($this->started >= $this->total) {
76 usleep((1.0/$this->per_second) * 1000000);
82 //echo "Sleep: " . ((1.0/$this->per_second) * 1000000) . "\n";
83 usleep((1.0/$this->per_second) * 1000000);
86 $this->displayResults();
87 //print_R($this->done);
91 var $keynames = array();
94 require_once 'System.php';
95 $curl = System::which('curl');
96 $this->cmd = implode(" ", array(
98 "--max-time " , $this->timeout ,
99 "-s -o /dev/null -k ",
100 "-H \"Host: {$this->host}\"",
102 "-w \"%{http_code},%{size_download},%{time_connect},%{time_starttransfer},%{time_total}\n\""
105 $sn = $_SERVER["SCRIPT_NAME"];
107 $this->cwd = $sn[0] == '/' ? dirname($sn) : dirname(realpath(getcwd() . '/'. $sn));
109 $this->keynames =array(
116 foreach($this->keynames as $k=>$v) {
117 $this->log[$v] = array();
128 $tn = $this->tempName('stdout', true);
129 $descriptorspec = array(
130 0 => array("pipe", 'r'), // stdin is a pipe that the child will read from
131 1 => array("file", $tn, 'w'), // stdout is a pipe that the child will write to
132 2 => array("pipe", "w") // stderr is a file to write to
136 //$cmd = 'exec ' . $php . ' ' . $app . ' ' . $cmdOpts; //. ' &';
141 //echo date("H:i:s"). ":Start: {$this->started} : {$this->cmd}\n";
143 $p = proc_open($this->cmd, $descriptorspec, $pipes, $this->cwd );
144 $info = proc_get_status($p);
147 $this->pool[] = array(
149 'pid' => $info['pid'],
151 'id' => $this->started,
165 foreach($this->pool as $p) {
168 $info = proc_get_status($p['proc']);
170 // update if necessday.
171 if ($info['pid'] && $p['pid'] != $info['pid']) {
172 $p['pid'] = $info['pid'];
176 if ($info['running']) {
184 fclose($p['pipes'][0]);
185 fclose($p['pipes'][2]);
186 proc_close($p['proc']);
187 $res = trim(file_get_contents($p['out']));
189 $p['data'] = explode(",", $res);
191 foreach($p['data'] as $i=>$v) {
192 $this->log[$this->keynames[$i]][] = $v;
194 $suc = $p['data'][0] == 200 ? 'Done' : 'Fail';
196 echo date("H:i:s"). ":{$suc}: ". (1+$p['id']). "/{$this->total}: ";
197 $this->displayResults();
208 function displayResults()
211 // we could slice log values to get recent.. // to show current trend.
214 $done = count($this->done);
216 "Success Rate: ". number_format(100*(count(array_filter($log['success'], function($s) { return $s == 200; })) / $done), 0) . '%'.
217 " Largest: " . number_format(max($log['size']),0) .'b'. // these ignore failures.
218 " Smallest: " . number_format(min($log['size']),0) .'b'.
219 " Av.Connect: ". number_format(array_sum($log['connect'])/$done, 2) .'s'.
220 " Average Before Output Time: ", number_format(array_sum($log['building'])/$done, 2) .'s'.
221 " Average Load Time: " .number_format(array_sum($log['sent'])/$done, 2) .'s' .
222 " Load: {$this->per_second} req/s" .