You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
574
vendor/swoole/benchmark/run.php
vendored
Executable file
574
vendor/swoole/benchmark/run.php
vendored
Executable file
@ -0,0 +1,574 @@
|
||||
<?php
|
||||
require __DIR__.'/../examples/websocket/WebSocketClient.php';
|
||||
|
||||
//关闭错误输出
|
||||
//error_reporting(0);
|
||||
$shortopts = "c:";
|
||||
$shortopts .= "n:";
|
||||
$shortopts .= "s:";
|
||||
$shortopts .= "f:";
|
||||
$shortopts .= "p::";
|
||||
|
||||
$opt = getopt($shortopts);
|
||||
//并发数量
|
||||
if(!isset($opt['c'])) exit("require -c [process_num]. ep: -c 100\n");
|
||||
if(!isset($opt['n'])) exit("require -n [request_num]. ep: -n 10000\n");
|
||||
if(!isset($opt['s'])) exit("require -s [server_url]. ep: -s tcp://127.0.0.1:9999\n");
|
||||
if(!isset($opt['f'])) exit("require -f [test_function]. ep: -f short_tcp\n");
|
||||
|
||||
$bc = new Swoole_Benchmark(trim($opt['f']));
|
||||
$bc->process_num = (int)$opt['c'];
|
||||
$bc->request_num = (int)$opt['n'];
|
||||
$bc->server_url = trim($opt['s']);
|
||||
$bc->server_config = parse_url($bc->server_url);
|
||||
$bc->send_data = "GET / HTTP/1.1\r\n";
|
||||
$bc->send_data .= "Host: www.baidu.com\r\n";
|
||||
$bc->send_data .= "Connection: keep-alive\r\n";
|
||||
$bc->send_data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n";
|
||||
$bc->send_data .= "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36\r\n\r\n";
|
||||
|
||||
$bc->read_len = 65536;
|
||||
if(!empty($opt['p'])) $bc->show_detail = true;
|
||||
|
||||
function eof(Swoole_Benchmark $bc)
|
||||
{
|
||||
static $client = null;
|
||||
static $i;
|
||||
$start = microtime(true);
|
||||
if (empty($client)) {
|
||||
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
|
||||
$client->set(array('open_eof_check' => true, "package_eof" => "\r\n\r\n"));
|
||||
$end = microtime(true);
|
||||
$conn_use = $end - $start;
|
||||
$bc->max_conn_time = $conn_use;
|
||||
$i = 0;
|
||||
//echo "connect {$bc->server_url} \n";
|
||||
if (!$client->connect($bc->server_config['host'], $bc->server_config['port'], 2)) {
|
||||
error:
|
||||
echo "Error: " . swoole_strerror($client->errCode) . "[{$client->errCode}]\n";
|
||||
$client = null;
|
||||
return false;
|
||||
}
|
||||
$start = $end;
|
||||
}
|
||||
/*--------写入Sokcet-------*/
|
||||
$data = str_repeat('A', rand(100, 200))."\r\n\r\n";
|
||||
if (!$client->send($data))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$write_use = $end - $start;
|
||||
if ($write_use > $bc->max_write_time) $bc->max_write_time = $write_use;
|
||||
$start = $end;
|
||||
/*--------读取Sokcet-------*/
|
||||
$i ++;
|
||||
$ret = $client->recv();
|
||||
if (empty($ret))
|
||||
{
|
||||
echo $bc->pid, "#$i", " is lost\n";
|
||||
return false;
|
||||
}
|
||||
elseif(strlen($ret) != strlen($data))
|
||||
{
|
||||
echo "#$i\tlength error\n";
|
||||
var_dump($ret);
|
||||
echo "-----------------------------------\n";
|
||||
var_dump($data);
|
||||
}
|
||||
$end = microtime(true);
|
||||
$read_use = $end - $start;
|
||||
if ($read_use > $bc->max_read_time) $bc->max_read_time = $read_use;
|
||||
return true;
|
||||
}
|
||||
|
||||
function long_tcp(Swoole_Benchmark $bc)
|
||||
{
|
||||
static $fp = null;
|
||||
static $i;
|
||||
$start = microtime(true);
|
||||
if(empty($fp))
|
||||
{
|
||||
$fp = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
|
||||
$end = microtime(true);
|
||||
$conn_use = $end-$start;
|
||||
$bc->max_conn_time = $conn_use;
|
||||
$i = 0;
|
||||
//echo "connect {$bc->server_url} \n";
|
||||
if (!$fp->connect($bc->server_config['host'], $bc->server_config['port'], 2))
|
||||
{
|
||||
error:
|
||||
echo "Error: ".swoole_strerror($fp->errCode)."[{$fp->errCode}]\n";
|
||||
$fp = null;
|
||||
return false;
|
||||
}
|
||||
$start = $end;
|
||||
}
|
||||
/*--------写入Sokcet-------*/
|
||||
if (!$fp->send($bc->send_data))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$write_use = $end - $start;
|
||||
if ($write_use > $bc->max_write_time)
|
||||
{
|
||||
$bc->max_write_time = $write_use;
|
||||
}
|
||||
$start = $end;
|
||||
/*--------读取Sokcet-------*/
|
||||
while(true)
|
||||
{
|
||||
$ret = $fp->recv(65530);
|
||||
if (empty($ret) or substr($ret, -1, 1) == "\n")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
//var_dump($ret);
|
||||
$i++;
|
||||
if (empty($ret))
|
||||
{
|
||||
echo $bc->pid, "#$i@", " is lost\n";
|
||||
return false;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$read_use = $end - $start;
|
||||
if ($read_use > $bc->max_read_time)
|
||||
{
|
||||
$bc->max_read_time = $read_use;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function websocket(Swoole_Benchmark $bc)
|
||||
{
|
||||
static $client = null;
|
||||
static $i;
|
||||
$start = microtime(true);
|
||||
|
||||
if (empty($client))
|
||||
{
|
||||
$client = new WebSocketClient($bc->server_config['host'], $bc->server_config['port']);
|
||||
if (!$client->connect())
|
||||
{
|
||||
echo "connect failed\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
$end = microtime(true);
|
||||
$conn_use = $end - $start;
|
||||
$bc->max_conn_time = $conn_use;
|
||||
$i = 0;
|
||||
$start = $end;
|
||||
}
|
||||
/*--------写入Sokcet-------*/
|
||||
if (!$client->send($bc->send_data))
|
||||
{
|
||||
echo "send failed\n";
|
||||
return false;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$write_use = $end - $start;
|
||||
if ($write_use > $bc->max_write_time)
|
||||
{
|
||||
$bc->max_write_time = $write_use;
|
||||
}
|
||||
$start = $end;
|
||||
/*--------读取Sokcet-------*/
|
||||
$ret = $client->recv();
|
||||
//var_dump($ret);
|
||||
$i++;
|
||||
if (empty($ret))
|
||||
{
|
||||
echo $bc->pid, "#$i@", " is lost\n";
|
||||
return false;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$read_use = $end - $start;
|
||||
if ($read_use > $bc->max_read_time)
|
||||
{
|
||||
$bc->max_read_time = $read_use;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉计时信息的UDP
|
||||
* @param $bc
|
||||
* @return bool
|
||||
*/
|
||||
function udp(Swoole_Benchmark $bc)
|
||||
{
|
||||
static $fp;
|
||||
if (empty($fp))
|
||||
{
|
||||
$fp = stream_socket_client($bc->server_url, $errno, $errstr, 1);
|
||||
if (!$fp)
|
||||
{
|
||||
echo "{$errstr}[{$errno}]\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*--------写入Sokcet-------*/
|
||||
fwrite($fp, $bc->send_data);
|
||||
/*--------读取Sokcet-------*/
|
||||
$ret = fread($fp, $bc->read_len);
|
||||
if (empty($ret))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function udp2(Swoole_Benchmark $bc)
|
||||
{
|
||||
static $fp;
|
||||
$start = microtime(true);
|
||||
if (empty($fp))
|
||||
{
|
||||
$u = parse_url($bc->server_url);
|
||||
$fp = new swoole_client(SWOOLE_SOCK_UDP);
|
||||
$fp->connect($u['host'], $u['port'], 0.5, 0);
|
||||
$end = microtime(true);
|
||||
$conn_use = $end - $start;
|
||||
$bc->max_conn_time = $conn_use;
|
||||
$start = $end;
|
||||
}
|
||||
/*--------写入Sokcet-------*/
|
||||
$fp->send($bc->send_data);
|
||||
$end = microtime(true);
|
||||
$write_use = $end - $start;
|
||||
if ($write_use > $bc->max_write_time)
|
||||
{
|
||||
$bc->max_write_time = $write_use;
|
||||
}
|
||||
$start = $end;
|
||||
/*--------读取Sokcet-------*/
|
||||
$ret = $fp->recv();
|
||||
if (empty($ret))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$end = microtime(true);
|
||||
$read_use = $end - $start;
|
||||
if ($read_use > $bc->max_read_time)
|
||||
{
|
||||
$bc->max_read_time = $read_use;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function short_tcp($bc)
|
||||
{
|
||||
$fp = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
|
||||
if(!$fp->connect($bc->server_config['host'], $bc->server_config['port'], 1))
|
||||
{
|
||||
error:
|
||||
echo "Error: ".socket_strerror($fp->errCode)."[{$fp->errCode}]\n";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!$fp->send($bc->send_data))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
$ret = $fp->recv();
|
||||
$fp->close();
|
||||
if(!empty($ret)) return true;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
|
||||
function long_socks5($bc)
|
||||
{
|
||||
static $fp = null;
|
||||
static $i;
|
||||
$start = microtime(true);
|
||||
if(empty($fp))
|
||||
{
|
||||
$fp = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC,5);
|
||||
$end = microtime(true);
|
||||
$conn_use = $end-$start;
|
||||
$bc->max_conn_time = $conn_use;
|
||||
$i = 0;
|
||||
//echo "connect {$bc->server_url} \n";
|
||||
if (!$fp->connect($bc->server_config['host'], $bc->server_config['port'], 2))
|
||||
{
|
||||
error:
|
||||
echo "Error: ".swoole_strerror($fp->errCode)."[{$fp->errCode}]\n";
|
||||
$fp = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
$fp->send(pack("C3", 0x05, 0x01, 0x00));//greet
|
||||
$data = $fp->recv();
|
||||
$response = unpack("Cversion/Cmethod", $data);
|
||||
if ($response['version'] != 0x05)
|
||||
{
|
||||
exit('SOCKS version is not supported.');
|
||||
}
|
||||
$headers = getHeader($bc->send_data);
|
||||
if (empty($headers['port'])) {
|
||||
$headers['port'] = 80;
|
||||
}
|
||||
$g = pack("C5", 0x05, 0x01, 0x00, 0x03, strlen($headers['host'])) . $headers['host'] . pack("n", $headers['port']);
|
||||
$fp->send($g);
|
||||
$data = $fp->recv();
|
||||
$response = unpack("Cversion/Cresult/Creg/Ctype/Lip/Sport", $data);
|
||||
if ($response['result'] != 0x00)
|
||||
{
|
||||
echo 'SOCKS connection request failed: ' . getSocksRefusalMsg($response['result']), $response['result'];exit;
|
||||
}
|
||||
|
||||
$start = $end;
|
||||
}
|
||||
/*--------写入Sokcet-------*/
|
||||
if (!$fp->send($bc->send_data))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$write_use = $end - $start;
|
||||
if ($write_use > $bc->max_write_time)
|
||||
{
|
||||
$bc->max_write_time = $write_use;
|
||||
}
|
||||
$start = $end;
|
||||
/*--------读取Sokcet-------*/
|
||||
while(true)
|
||||
{
|
||||
$ret = $fp->recv(65530);
|
||||
if (empty($ret) or substr($ret, -1, 1) == "\n")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
//var_dump($ret);
|
||||
$i++;
|
||||
if (empty($ret))
|
||||
{
|
||||
echo $bc->pid, "#$i@", " is lost\n";
|
||||
return false;
|
||||
}
|
||||
$end = microtime(true);
|
||||
$read_use = $end - $start;
|
||||
if ($read_use > $bc->max_read_time)
|
||||
{
|
||||
$bc->max_read_time = $read_use;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getHeader($message)
|
||||
{
|
||||
// 标准每行应该以"\r\n"行终止,这里兼容以"\n"作为行终止的情况,所以按"\n"分割行
|
||||
$lines = explode("\n", $message);
|
||||
foreach ($lines as &$line)
|
||||
{
|
||||
// 按"\n"分割行以后,某些行末可能存在"\r"字符,这里将其过滤掉
|
||||
$line = rtrim($line, "\r");
|
||||
}
|
||||
unset($line);
|
||||
|
||||
if (count($lines) <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$headers = [];
|
||||
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
$pos = strpos($line, ':');
|
||||
// 非标准首部,抛弃
|
||||
if ($pos === false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$field = trim(substr($line, 0, $pos));
|
||||
$value = trim(substr($line, $pos + 1));
|
||||
|
||||
// 如果有host头部,重新设置host和port
|
||||
if (strtolower($field) === 'host')
|
||||
{
|
||||
$segments = explode(':', $value);
|
||||
$host = $segments[0];
|
||||
$headers['host'] = $host;
|
||||
if (isset($segments[1]))
|
||||
{
|
||||
$port = intval($segments[1]);
|
||||
$headers['port'] = $port;
|
||||
}
|
||||
}
|
||||
$headers[$field] = $value;
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
//请求数量最好是进程数的倍数
|
||||
$bc->process_req_num = intval($bc->request_num/$bc->process_num);
|
||||
$bc->run();
|
||||
$bc->report();
|
||||
$bc->end();
|
||||
|
||||
class Swoole_Benchmark
|
||||
{
|
||||
public $test_func;
|
||||
public $process_num;
|
||||
public $request_num;
|
||||
public $server_url;
|
||||
public $server_config;
|
||||
public $send_data;
|
||||
public $read_len;
|
||||
|
||||
public $time_end;
|
||||
private $shm_key;
|
||||
public $main_pid;
|
||||
public $child_pid = array();
|
||||
|
||||
public $show_detail = false;
|
||||
public $max_write_time = 0;
|
||||
public $max_read_time = 0;
|
||||
public $max_conn_time = 0;
|
||||
|
||||
public $pid;
|
||||
|
||||
protected $tmp_dir = '/tmp/swoole_bench/';
|
||||
|
||||
function __construct($func)
|
||||
{
|
||||
if (!function_exists($func))
|
||||
{
|
||||
exit(__CLASS__ . ": function[$func] not exists\n");
|
||||
}
|
||||
if (!is_dir($this->tmp_dir))
|
||||
{
|
||||
mkdir($this->tmp_dir);
|
||||
}
|
||||
$this->test_func = $func;
|
||||
}
|
||||
function end()
|
||||
{
|
||||
unlink($this->shm_key);
|
||||
foreach($this->child_pid as $pid)
|
||||
{
|
||||
$f = $this->tmp_dir . 'lost_' . $pid . '.log';
|
||||
if (is_file($f)) unlink($f);
|
||||
}
|
||||
}
|
||||
|
||||
function run()
|
||||
{
|
||||
$this->main_pid = posix_getpid();
|
||||
$this->shm_key = $this->tmp_dir.'t.log';
|
||||
for ($i = 0; $i < $this->process_num; $i++)
|
||||
{
|
||||
$this->child_pid[] = $this->start(array($this, 'worker'));
|
||||
}
|
||||
for ($i = 0; $i < $this->process_num; $i++)
|
||||
{
|
||||
$status = 0;
|
||||
$pid = pcntl_wait($status);
|
||||
}
|
||||
$this->time_end = microtime(true);
|
||||
}
|
||||
|
||||
function init_signal()
|
||||
{
|
||||
pcntl_signal(SIGUSR1,array($this, "sig_handle"));
|
||||
}
|
||||
|
||||
function sig_handle($sig)
|
||||
{
|
||||
switch ($sig)
|
||||
{
|
||||
case SIGUSR1:
|
||||
return;
|
||||
}
|
||||
$this->init_signal();
|
||||
}
|
||||
|
||||
function start($func)
|
||||
{
|
||||
$pid = pcntl_fork();
|
||||
if($pid>0)
|
||||
{
|
||||
return $pid;
|
||||
}
|
||||
elseif($pid==0)
|
||||
{
|
||||
$this->worker();
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Error:fork fail\n";
|
||||
}
|
||||
}
|
||||
function worker()
|
||||
{
|
||||
$lost = 0;
|
||||
if(!file_exists($this->shm_key))
|
||||
{
|
||||
file_put_contents($this->shm_key,microtime(true));
|
||||
}
|
||||
if($this->show_detail) $start = microtime(true);
|
||||
$this->pid = posix_getpid();
|
||||
|
||||
for ($i = 0; $i < $this->process_req_num; $i++)
|
||||
{
|
||||
$func = $this->test_func;
|
||||
if(!$func($this)) $lost++;
|
||||
}
|
||||
if ($this->show_detail)
|
||||
{
|
||||
$log = $this->pid . "#\ttotal_use(s):" . substr(microtime(true) - $start, 0, 5);
|
||||
$log .= "\tconnect(ms):" . substr($this->max_conn_time * 1000, 0, 5);
|
||||
$log .= "\twrite(ms):" . substr($this->max_write_time * 1000, 0, 5);
|
||||
$log .= "\tread(ms):" . substr($this->max_read_time * 1000, 0, 5);
|
||||
file_put_contents($this->tmp_dir.'lost_' . $this->pid . '.log', $lost . "\n" . $log);
|
||||
}
|
||||
else
|
||||
{
|
||||
file_put_contents($this->tmp_dir.'lost_'.$this->pid.'.log', $lost);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
function report()
|
||||
{
|
||||
$time_start = file_get_contents($this->shm_key);
|
||||
$usetime = $this->time_end - $time_start;
|
||||
$lost = 0;
|
||||
|
||||
foreach ($this->child_pid as $f)
|
||||
{
|
||||
$file = $this->tmp_dir.'lost_'.$f.'.log';
|
||||
if (is_file($file))
|
||||
{
|
||||
$_lost = file_get_contents($file);
|
||||
$log = explode("\n",$_lost,2);
|
||||
}
|
||||
if (!empty($log))
|
||||
{
|
||||
$lost += intval($log[0]);
|
||||
if ($this->show_detail) echo $log[1], "\n";
|
||||
}
|
||||
}
|
||||
//并发量
|
||||
echo "concurrency:\t".$this->process_num,"\n";
|
||||
//请求量
|
||||
echo "request num:\t".$this->request_num,"\n";
|
||||
//请求量
|
||||
echo "lost num:\t".$lost,"\n";
|
||||
//请求量
|
||||
echo "success num:\t".($this->request_num-$lost),"\n";
|
||||
//总时间
|
||||
echo "total time:\t".substr($usetime,0,5),"\n";
|
||||
//每秒处理能力
|
||||
echo "req per second:\t".intval($this->request_num/$usetime),"\n";
|
||||
//每次请求平均时间ms
|
||||
echo "one req use(ms):\t".substr($usetime/$this->request_num*1000,0,5),"\n";
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user