From 9c7ccf2f70cadca14e11127694543b2b1f4e8c7e Mon Sep 17 00:00:00 2001 From: Alan Date: Tue, 17 Jan 2023 16:33:53 +0800 Subject: [PATCH] add load test --- Import/Core_templatestr.php | 34 ++++- Pman.Tab.AdminTranslations.bjs | 3 +- Pman.Tab.AdminTranslations.js | 3 +- Tools/LoadTest.php | 233 +++++++++++++++++++++++++++++++++ 4 files changed, 268 insertions(+), 5 deletions(-) create mode 100644 Tools/LoadTest.php diff --git a/Import/Core_templatestr.php b/Import/Core_templatestr.php index fe0f851..47ace8d 100644 --- a/Import/Core_templatestr.php +++ b/Import/Core_templatestr.php @@ -93,10 +93,39 @@ class Pman_Admin_Import_Core_templatestr extends Pman } return $ret; } - + function updateTranslation($r) + { + // determine the type of file: + + if (empty($r['template']) || empty($r['module']) || empty($r['code'])) { + $this->jerr("missing template / module or code column"); + } + if (isset($r['language'])) { + $this->updateTableTranslationRow($r); + return; + } + $ff = HTML_FlexyFramework::get(); + if (!isset($ff->Pman_Admin['languages'])) { + $this->jerr("invalid language configuration"); + } + + + foreach($ff->Pman_Admin['languages'] as $lang) { + if (!isset($r[strtolower($lang)])) { + //echo "SKIP $lang\n"; + continue; + } + $rr = $r; + $rr['language'] = $lang; + $rr['translation'] = $r[strtolower($lang)]; + $this->updateTranslationRow($rr); + } + + + } var $seq = 1; - function updateTranslation($r) + function updateTranslationRow($r) { //print_R($r); DB_DataObject::DebugLevel(1); $tr = DB_DataObject::Factory('core_templatestr'); @@ -114,7 +143,6 @@ class Pman_Admin_Import_Core_templatestr extends Pman $tt->txt = $r['translation']; $tt->updated = date('Y-m-d H:i:s'); $tt->update($tr); - return 1; } return 0; diff --git a/Pman.Tab.AdminTranslations.bjs b/Pman.Tab.AdminTranslations.bjs index 34ef06f..97441f0 100644 --- a/Pman.Tab.AdminTranslations.bjs +++ b/Pman.Tab.AdminTranslations.bjs @@ -247,7 +247,8 @@ " csvTitles : 'Code,Module,Template,Original,Language,Translation',", " limit : 9999,", " sort: 'template_id_view_name,template_id_template,src_id_txt',", - " dir: 'ASC'", + " dir: 'ASC',", + " active : 1", " };", " if (!sn || sn.id == 'transtree') {", " Roo.MessageBox.alert(\"Error\", \"Select language, module or page\");", diff --git a/Pman.Tab.AdminTranslations.js b/Pman.Tab.AdminTranslations.js index 1d5e235..b0d95d5 100644 --- a/Pman.Tab.AdminTranslations.js +++ b/Pman.Tab.AdminTranslations.js @@ -295,7 +295,8 @@ Pman.Tab.AdminTranslations = new Roo.XComponent({ csvTitles : 'Code,Module,Template,Original,Language,Translation', limit : 9999, sort: 'template_id_view_name,template_id_template,src_id_txt', - dir: 'ASC' + dir: 'ASC', + active : 1 }; if (!sn || sn.id == 'transtree') { Roo.MessageBox.alert("Error", "Select language, module or page"); diff --git a/Tools/LoadTest.php b/Tools/LoadTest.php new file mode 100644 index 0000000..9925841 --- /dev/null +++ b/Tools/LoadTest.php @@ -0,0 +1,233 @@ + array( + 'desc' => 'Request per second (default 1)', + 'default' => '2', + 'short' => 'P', + 'max' => 1 + + ), + + 'timeout' => array( + 'desc' => 'Timeout in seconds', + 'default' => '5', + 'short' => 'T' , + 'max' => 1 + ), + 'total' => array( + 'desc' => 'Total tests (20)', + 'default' => '20', + 'short' => 't' , + 'max' => 1 + ), + + ); + // try and do some load testing.. + var $total = 20; // total number of tests to run. + var $timeout = 5; // for each request. + var $per_second = 2; // how many per second. + var $host = 'www-new.regulationasia.com'; + var $url = 'https://sg2-web.regulationasia.com/'; + + var $cmd = ""; // filled in by initCmd + + var $started = 0; + var $done = array(); + var $pool = array(); + function get($r,$opts=array()) + { + + // print_R($opts);exit; + foreach($opts as $k=>$v) { + $this->{$k} = $v; + } + $this->initCmd(); + + echo "Run: + +Request Per Second: {$this->per_second} +No. Requests : {$this->total} +Timeout: {$this->timeout} +URL: {$this->url} +Host: {$this->host} +CMD: {$this->cmd} + +"; + + + while (true) { + + + $ps = $this->poolsize(); + + if ($this->started >= $this->total) { + if ($ps == 0) { + break; + } + usleep((1.0/$this->per_second) * 1000000); + continue; + } + // run it.. + $this->run(); + $this->started++; + //echo "Sleep: " . ((1.0/$this->per_second) * 1000000) . "\n"; + usleep((1.0/$this->per_second) * 1000000); + + } + $this->displayResults(); + //print_R($this->done); + exit; + } + var $log = array(); + var $keynames = array(); + function initCmd() + { + require_once 'System.php'; + $curl = System::which('curl'); + $this->cmd = implode(" ", array( + $curl, + "--max-time " , $this->timeout , + "-s -o /dev/null -k ", + "-H \"Host: {$this->host}\"", + "\"{$this->url}\"", + "-w \"%{http_code},%{size_download},%{time_connect},%{time_starttransfer},%{time_total}\n\"" + )); + + $sn = $_SERVER["SCRIPT_NAME"]; + + $this->cwd = $sn[0] == '/' ? dirname($sn) : dirname(realpath(getcwd() . '/'. $sn)); + + $this->keynames =array( + 'success', + 'size', + 'connect', + 'building', + 'sent' + ); + foreach($this->keynames as $k=>$v) { + $this->log[$v] = array(); + } + + + } + + function run() + { + + + + $tn = $this->tempName('stdout', true); + $descriptorspec = array( + 0 => array("pipe", 'r'), // stdin is a pipe that the child will read from + 1 => array("file", $tn, 'w'), // stdout is a pipe that the child will write to + 2 => array("pipe", "w") // stderr is a file to write to + ); + + + //$cmd = 'exec ' . $php . ' ' . $app . ' ' . $cmdOpts; //. ' &'; + + + $pipe = array(); + + //echo date("H:i:s"). ":Start: {$this->started} : {$this->cmd}\n"; + + $p = proc_open($this->cmd, $descriptorspec, $pipes, $this->cwd ); + $info = proc_get_status($p); + + + $this->pool[] = array( + 'proc' => $p, + 'pid' => $info['pid'], + 'out' => $tn, + 'id' => $this->started, + //'cmd' => $cmd, + 'pipes' => $pipes, + 'started' => time() + ); + } + + + + function poolsize() + { + $pool = array(); + clearstatcache(); + + foreach($this->pool as $p) { + + + $info = proc_get_status($p['proc']); + + // update if necessday. + if ($info['pid'] && $p['pid'] != $info['pid']) { + $p['pid'] = $info['pid']; + } + + + if ($info['running']) { + + $pool[] = $p; + continue; + } + // closed... + + + fclose($p['pipes'][0]); + fclose($p['pipes'][2]); + proc_close($p['proc']); + $res = trim(file_get_contents($p['out'])); + + $p['data'] = explode(",", $res); + $this->done[] = $p; + foreach($p['data'] as $i=>$v) { + $this->log[$this->keynames[$i]][] = $v; + } + $suc = $p['data'][0] == 200 ? 'Done' : 'Fail'; + + echo date("H:i:s"). ":{$suc}: ". (1+$p['id']). "/{$this->total}: "; + $this->displayResults(); + + + @unlink($p['out']); + + } + $this->pool = $pool; + return count($pool); + + } + + function displayResults() + { + $log = $this->log; + // we could slice log values to get recent.. // to show current trend. + + + $done = count($this->done); + echo + "Success Rate: ". number_format(100*(count(array_filter($log['success'], function($s) { return $s == 200; })) / $done), 0) . '%'. + " Largest: " . number_format(max($log['size']),0) .'b'. // these ignore failures. + " Smallest: " . number_format(min($log['size']),0) .'b'. + " Av.Connect: ". number_format(array_sum($log['connect'])/$done, 2) .'s'. + " Average Before Output Time: ", number_format(array_sum($log['building'])/$done, 2) .'s'. + " Average Load Time: " .number_format(array_sum($log['sent'])/$done, 2) .'s' . + " Load: {$this->per_second} req/s" . + "\n"; + + + + + + + + } + +} \ No newline at end of file -- 2.39.2