swoole server中的定时器不准确出现抖动的情况,求解答

定时器打印的日志出现抖动情况,如下:
timer: ##23496 ##2016-09-01 19:23:24
timer: ##23496 ##2016-09-01 19:23:25
timer: ##23496 ##2016-09-01 19:23:27
timer: ##23496 ##2016-09-01 19:23:27
timer: ##23496 ##2016-09-01 19:23:28
timer: ##23496 ##2016-09-01 19:23:29
timer: ##23496 ##2016-09-01 19:23:30
timer: ##23496 ##2016-09-01 19:23:31
timer: ##23496 ##2016-09-01 19:23:33
timer: ##23496 ##2016-09-01 19:23:33
timer: ##23496 ##2016-09-01 19:23:36
timer: ##23496 ##2016-09-01 19:23:37
timer: ##23496 ##2016-09-01 19:23:39
timer: ##23496 ##2016-09-01 19:23:39
timer: ##23496 ##2016-09-01 19:23:40
timer: ##23496 ##2016-09-01 19:23:41
timer: ##23496 ##2016-09-01 19:23:42
timer: ##23496 ##2016-09-01 19:23:43
timer: ##23496 ##2016-09-01 19:23:45

是不是timer中process signal注册有问题?还是signal和server搭配使用有问题?
代码如下:

<?php
class box{ static $list = array; static function processDo { $echo = timer: ##. posix_getpid . ##. date Y-m-d H:i:s.PHP_EOL; file_put_contents /tmp/xx.log , $echo , FILE_APPEND ; $process = new swoole_process function swoole_process $worker { swoole_set_process_name lau_php_process . posix_getpid ; exec php -i , $output , $status ; echo process: . posix_getpid . :: exec.status . $status . PHP_EOL; sleep5; $worker->exit1; }; if !$pid = $process->start { } box::$list[$pid] = array "start" => microtimetrue, "process" =>$process, ; } static function registerSingal { swoole_process::signalSIGTERM, function $signo { exit; }; swoole_process::signal SIGCHLD, function $signo { while $ret = swoole_process::waitfalse { $pidx = $ret[ pid ]; print_r $ret ; print_r self::$list ; if isset self::$list[ $pidx ] { echo "SIGNAL: $signo
"; $end = microtimetrue; $start = box::$list[$pidx]["start"]; echo "##{$pidx} exit... [Runtime:" . sprintf"%0.6f", $end - $start . "]".PHP_EOL; unset box::$list[$pidx] ; } else { echo "nono SIGNAL: $signo
"; } } }; }
} ####################################################################################################
$http = new swoole_http_server"0.0.0.0",9501,SWOOLE_BASE;
//初始化swoole服务
$http->setarray task_worker_num => 2, worker_num => 2, daemonize => 0, //是否作为守护进程,此配置一般配合log_file使用 max_request => 1000, dispatch_mode => 2, debug_mode => 1, log_file => ./swoole.log,
; $http->onStart, function{ echo start pid# . posix_getpid . # . __LINE__ . PHP_EOL; echo SWOOLE_VERSION . " onStart
";
} ;
$http->onWorkerStart, function $serv , $worker_id use $http { // 在Worker进程开启时绑定定时器 swoole_set_process_name lau_php_worker . posix_getpid ; // 只有当worker_id为0时才添加定时器,避免重复添加 if $worker_id == 0 { box::registerSingal; swoole_timer_tick1000,function $params { box::processDo; }; }
};
$http->onrequest,function$request,$response use $http { echo ____request pid# . posix_getpid . # . __LINE__ . PHP_EOL; $out = json_encodebox::$list; $response->end$out;
}; $http->on task, function$http, $taskId, $fromId, $request{ echo +++++task:.$http->worker_pid.PHP_EOL; return ;
}; $server = $http;
$http->on finish , function$server, $taskId, $ret
{
};
swoole_set_process_name lau_php_main . posix_getpid ;
$http->start;

你这个属于正常现象,您可以打开计算机时钟设置看看秒数是不是4秒短5秒长的规律?具体看下面

前一阵子,松鼠会中有人提到,Windows 系统中的秒针走起来,前四秒快,而后一秒慢。然后又说是今年才开始的,预示着地球的剧变,等等不着边际的话。很不以为然。但是,这种快慢不一的现象原来是真的,现在有人提供了一个解释,是程序的问题:

如果你细心注意过的话,点开2K/XP/2K3系统右下角的时钟,让他的秒针走动起来的时候,会出现一个很有意思的现象:前四秒钟数字和秒针变化的快,第五秒感觉却很长,这是为什么呢?

原因实际上出在那个表的精度上。

如果学过Windows的C++编程可以知道,WM_TIMER是常用的定时器。但这个定时器的精度不是很高。在Windows的Clock这个子程序中,实际上就是用了WM_TIMER进行定时。当显示秒针时,表的更新由这样一句语句触发:

SetTimer hWnd, TimerID, OPEN_TLEN, 0L;

SetTimer的用法很简单,设置好Timer之后,每次触发就只要重新取当前时间重画表盘就可以了。那么OPEN_TLEN就是Timer的触发时间。这个时间是一个常量,在受到影响的系统里面被定义为450,也就是不到半秒。

定义成450ms会出现什么现象?我们来看一组数。第一行和第三行是更新的次数,他们下面是更新的毫秒数。

 1   2    3    4    5    6    7    8
450 900 1350 1800 2250 2700 3150 3600

  9   10   11   12   13   14   15   16   17
4050 4500 4950 5400 5850 6300 6750 7200 7650

可以看到,在第一秒内(<1000)表实际上进行了两次更新,第二秒、第三秒、第四秒都是如此。而第五秒的时候,你就需要等三次更新才能看到 (注意 9、10、11都是4xxx的样子)。因此就出现了这个怪异的现象:前四次都是数两下就会跳一秒,第五次要数三下才跳一秒,第五秒的出现时间比前四秒都多 了50%,所以就感觉很长了。

那为什么要设计成这样?大概是因为这个表只是让你有个时间观念,只要不走错,秒级的响应并不重要吧……毕竟这个世界上没有多少人一天到晚盯着秒针数拍子的。

以上解释来自 opal.

发表评论

电子邮件地址不会被公开。 必填项已用*标注