共计 3932 个字符,预计需要花费 10 分钟才能阅读完成。
不晓得大家还记得在学校的时候体育测试时老师带的秒表吗?当枪声想起时,咱们开始跑步,这时秒表启动,当咱们跑过起点后,老师会按下按扭记录咱们的问题,这就是一个典型的定时器的利用。明天咱们要学习的内容其实就是和这个体育测验的秒表相似的一个性能扩大,它就是 PHP 的 HRTime 扩大。
时钟节奏
首先咱们要理解一下什么叫做零碎的时钟节奏。当 Linux 系统启动之后,会同时启动一个时钟节拍器,以纳秒为单位进行计时,而咱们的 HRTime 扩大的实在名称是 高精度工夫 扩大。也就是说,它正是基于操作系统的时钟节拍器,可能以纳秒为单位进行计时。
1 秒 =1000 毫秒 =1000000 奥妙 =1000000000 纳秒,这是秒、毫秒、微秒和纳秒的关系,看进去它的精度有多高了吧。1 秒等于 10 亿纳秒,这样咱们就能够取得一个十分准确的工夫距离计数。
HRTime 扩大间接在 PECL 进行下载安装就能够了,和其余的一般扩大没有什么区别。
获取零碎时钟节奏信息 Ticks
咱们先来看看如何获取操作系统的时钟节奏,也就是这个 Ticks。对于它的内容在学习操作系统的时候置信曾经有不少的同学接触过了,这里咱们看看应用 HRTime 扩大如何获取。
print_r(hrtime());
// Array
// (// [0] => 3758
// [1] => 407409171
// )
echo hrtime(true), PHP_EOL;
// 3758407428932
hrtime() 这个函数在 PHP7 之后曾经集成在默认 PHP 环境中了。它不须要 HRTime 扩大就能够应用。这个函数在没有参数的状况下返回的是一个数组,第 0 项是系统启动到当初的秒数,第 1 项就是对应的纳秒计数。如果给它的参数设置一个 true 的话,它将间接返回将秒和纳秒拼接起来的理论纳秒工夫戳。
echo HRTime\PerformanceCounter::getFrequency(), PHP_EOL; // 1000000000
echo HRTime\PerformanceCounter::getTicks(), PHP_EOL; // 3758428256236
echo HRTime\PerformanceCounter::getTicksSince(1212), PHP_EOL; // 3758428257494
$a = HRTime\PerformanceCounter::getTicks();
echo HRTime\PerformanceCounter::getTicksSince($a), PHP_EOL; // 412
接下来的这三个函数就是 HRTime 扩大中的 PerformanceCounter 对象的动态函数了。PerformanceCounter 对象的意思是性能计数器,getFrequency() 示意的是计时器频率(以滴答 Ticks/ 秒为单位),能够看出,它返回的就是纳秒单位,也就是 10 亿。getTicks() 返回的是以后的时钟节奏工夫,能够看出它和 hrtime(true) 函数的后果是一样的,都是返回的系统启动后的时钟节奏工夫。getTicksSince() 办法则是依据指定的纳秒数返回工夫距离,相似于 date_diff() 的感觉,其实就像咱们的 time() – time() 这样的操作。通过这个办法就能够取得一段代码两次运行的工夫距离,而且是以纳秒为单位哦。
定时器性能
接下来就是咱们文章的重点内容了,也就是定时器性能的实现。下面曾经说过,应用 getTickSince() 其实也能做到监控一段代码的运行工夫距离,不过上面将学习到的内容将更加弱小。
$c = new HRTime\StopWatch;
$c->start();
for ($i = 0; $i < 1024*1024; $i++);
echo 'isRunning:', $c->isRunning(), PHP_EOL; // isRunning: 1
$c->stop();
echo 'Time NS:', $c->getLastElapsedTime(HRTime\Unit::NANOSECOND), PHP_EOL;
echo 'Time US:', $c->getLastElapsedTime(HRTime\Unit::MICROSECOND), PHP_EOL;
echo 'Time MS:', $c->getLastElapsedTime(HRTime\Unit::MILLISECOND), PHP_EOL;
echo 'Time S:', $c->getLastElapsedTime(HRTime\Unit::SECOND), PHP_EOL;
// Time NS: 6929888
// Time US: 6929.888
// Time MS: 6.929888
// Time S: 0.006929888
echo 'Ticks:',$c->getLastElapsedTicks(), PHP_EOL;
// Ticks: 6929888
echo 'isRunning:',$c->isRunning(), PHP_EOL;
//
咱们须要实例化一个 StopWatch 对象,而后调用它的 start() 办法,这样一个定时器就启动了。StopWatch 的英文涵义自身就是定时器的意思,所以这个对象是专门为定时器的操作所服务的。通过 isRunning() 办法咱们能够判断以后定时器是否运行,其实就是判断以后是否是在一个 start() 办法之后,如果不在 start() 和 stop() 范畴中,那么它将返回 false。在测试代码中,咱们运行一个 1024*1024 的空循环,而后再应用 stop() 办法完结定时器。
从代码中能够看出,getLastElapsedTime() 就是取得咱们下面的那个 start() 到 stop() 之间的代码运行耗时的工夫距离信息,它的参数能够指定为秒、毫秒、微秒、纳秒。自身这个办法的意思就是获取获取最初一个距离的运行工夫。getLastElapsedTicks() 则是取得最初一次距离的时钟节奏信息。既然有【最初一次】这四个字,那么也就阐明这个对象是能够屡次调用的来分段计时的。并且,它还是能够将多段不同的计时进行汇总,取得全副的工夫距离信息的。
// 不在计时范畴内
for ($i = 0; $i < 1024*1024; $i++);
$c->start();
for ($i = 0; $i < 1024*1024; $i++);
$c->stop();
echo 'Time NS:', $c->getLastElapsedTime(HRTime\Unit::NANOSECOND), PHP_EOL;
echo 'Time US:', $c->getLastElapsedTime(HRTime\Unit::MICROSECOND), PHP_EOL;
echo 'Time MS:', $c->getLastElapsedTime(HRTime\Unit::MILLISECOND), PHP_EOL;
echo 'Time S:', $c->getLastElapsedTime(HRTime\Unit::SECOND), PHP_EOL;
// Time NS: 7154010
// Time US: 7154.01
// Time MS: 7.15401
// Time S: 0.00715401
echo 'All Time NS:', $c->getElapsedTime(HRTime\Unit::NANOSECOND), PHP_EOL;
echo 'All Time US:', $c->getElapsedTime(HRTime\Unit::MICROSECOND), PHP_EOL;
echo 'All Time MS:', $c->getElapsedTime(HRTime\Unit::MILLISECOND), PHP_EOL;
echo 'All Time S:', $c->getElapsedTime(HRTime\Unit::SECOND), PHP_EOL;
// All Time NS: 14083898
// All Time US: 14083.898
// All Time MS: 14.083898
// All Time S: 0.014083898
echo 'All Ticks:', $c->getElapsedTicks(), PHP_EOL;
// All Ticks: 14083898
在这段代码中,咱们在两段计时测试代码中插入了一个循环测试代码,它不会计入到计时数据中。接着,咱们从新 start() 开始一个新的计时,在最初,咱们通过 getElapsedTime() 和 getElapsedTicks() 两个办法取得总的计时工夫,能够看出下面的 6929888 加上这次的 7154010 后果正好是 14083898。两头的那一段没有在定时器中的循环代码没有计入到总的计时工夫中。
总结
是不是很有意思,它的作用真的和咱们的体育老师所用的那个秒表截然不同,老师们的秒表也都是能够按屡次记录第 1 名到最初 1 名的全副跑步问题,并且最初还有一个总的工夫,而在代码中咱们也是齐全类似的操作。这个扩大对于精密的性能调试十分有用,而且也可能针对一些须要这种高精度时间差的业务进行相干的开发。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/3. 学习 PHP 中的高精度计时器 HRTime 扩大.php
参考文档:
https://www.php.net/manual/zh/book.hrtime.php
https://www.cnblogs.com/chezxiaoqiang/archive/2012/03/23/2674386.html
各自媒体平台均可搜寻【硬核项目经理】