当前位置: 首页 > 后端技术 > PHP

学习PHP中的高精度定时器HRTime扩展

时间:2023-03-30 05:28:54 PHP

不知道大家还记得学校体育考试时老师带的秒表吗?枪声响起,我们开始奔跑,秒表开始计时。当我们通过终点线时,老师会按下按钮记录我们的成绩。这是定时器的典型应用。我们今天要学习的其实是一个类似这个体育竞猜秒表的功能扩展,就是PHP的HRTime扩展。时钟节拍首先,我们需要了解什么叫系统的时钟节拍。Linux系统启动时,会同时启动一个时钟节拍器,时间是以纳秒为单位计量的,而我们的HRTime扩展本名是高精度时间扩展。换句话说,它是一个基于操作系统的时钟节拍器,能够以纳秒为单位进行计时。1秒=1000毫秒=1000000微秒=1000000000纳秒。这就是秒、毫秒、微秒、纳秒之间的关系。你可以看到它的准确性有多高。1秒等于10亿纳秒,因此我们可以得到非常精确的时间间隔计数。HRTime扩展可以直接在PECL中下载安装,与其他普通扩展没有区别。获取系统时钟节拍信息Ticks我们先来看看如何获??取操作系统的时钟节拍,也就是Ticks。相信很多同学在学习操作系统的时候都接触过它的内容。在这里我们将看到如何使用HRTime扩展来获取它。print_r(hrtime());//Array//(//[0]=>3758//[1]=>407409171//)echohrtime(true),PHP_EOL;//3758407428932hrtime()这个函数是PHP7之后的已经集成在默认的PHP环境中。它在没有HRTime扩展的情况下工作。该函数返回一个不带参数的数组,第0项是系统启动后的秒数,第1项是对应的纳秒数。如果为其参数设置为真,它将直接返回与秒和纳秒连接的实际纳秒时间戳。echoHRTime\PerformanceCounter::getFrequency(),PHP_EOL;//1000000000echoHRTime\PerformanceCounter::getTicks(),PHP_EOL;//3758428256236echoHRTime\PerformanceCounter::getTicksSince(1212),PHP_EOL;//3758HRTimeunter42$8257::getTicks();echoHRTime\PerformanceCounter::getTicksSince($a),PHP_EOL;//412接下来的三个函数是HRTime扩展中的PerformanceCounter对象的静态函数。PerformanceCounter对象表示性能计数器,getFrequency()表示计时器频率(以滴答/秒为单位)。可以看出它返回的单位是纳秒,也就是10亿。getTicks()返回当前时钟节拍时间。可以看出和hrtime(true)函数的结果一样,都是系统启动后返回的时钟滴答时间。getTicksSince()方法按照指定的纳秒数返回时间间隔,和date_diff()的感觉类似,其实就是像我们的time()-time()操作。通过这个方法可以得到一段代码两次运行的时间间隔,单位是纳秒。定时器功能接下来是我们文章的重点内容,就是定时器功能的实现。上面说了,使用getTickSince()其实可以监控一段代码的运行时间间隔,但是下面要学的会更厉害。$c=newHRTime\StopWatch;$c->start();for($i=0;$i<1024*1024;$i++);echo'isRunning:',$c->isRunning(),PHP_EOL;//isRunning:1$c->stop();echo'TimeNS:',$c->getLastElapsedTime(HRTime\Unit::NANOSECOND),PHP_EOL;echo'TimeUS:',$c->getLastElapsedTime(HRTime\Unit::MICROSECOND),PHP_EOL;echo'TimeMS:',$c->getLastElapsedTime(HRTime\Unit::MILLISECOND),PHP_EOL;echo'时间S:',$c->getLastElapsedTime(HRTime\Unit::SECOND),PHP_EOL;//NS时间:6929888//US时间:6929.888//MS时间:6.929888//S时间:0.006929888echo'Ticks:',$c->getLastElapsedTicks(),PHP_EOL;//Ticks:6929888echo'isRunning:',$c->isRunning(),PHP_EOL;//我们需要实例化一个StopWatch对象,然后调用它的start()方法,这样计时器启动。StopWatch的英文意思本身就是定时器的意思,所以这个对象就是专门用来对定时器进行操作的。通过isRunning()方法,我们可以判断当前定时器是否在运行。其实就是判断是否在一个start()方法之后。如果不在start()和stop()的范围内,则返回false。在测试代??码中,我们运行一个1024*1024的空循环,然后使用stop()方法结束定时器。从代码中可以看出,getLastElapsedTime()就是获取我们上面start()和stop()之间代码运行的时间间隔信息。它的参数可以指定为秒、毫秒、微秒和纳秒。这个方法本身的意思就是获取最后一个区间的运行时间。getLastElapsedTicks()是获取最后一个区间的时钟节拍信息。既然有[lasttime]四个字,说明可以多次调用这个对象来分段计时。而且,它还可以聚合多个不同的定时,得到所有的时间间隔信息。//不在计算时间范围内for($i=0;$i<1024*1024;$i++);$c->start();for($i=0;$i<1024*1024;$i++);$c->stop();echo'TimeNS:',$c->getLastElapsedTime(HRTime\Unit::NANOSECOND),PHP_EOL;echo'TimeUS:',$c->getLastElapsedTime(HRTime\Unit::MICROSECOND),PHP_EOL;echo'TimeMS:',$c->getLastElapsedTime(HRTime\Unit::MILLISECOND),PHP_EOL;echo'TimeS:',$c->getLastElapsedTime(HRTime\Unit::SECOND),PHP_EOL;//NS时间:7154010//US时间:7154.01//MS时间:7.15401//S时间:0.00715401echo'AllTimeNS:',$c->getElapsedTime(HRTime\Unit::NANOSECOND),PHP_EOL;echo'美国所有时间:',$c->getElapsedTime(HRTime\Unit::MICROSECOND),PHP_EOL;echo'所有时间MS:',$c->getElapsedTime(HRTime\Unit::MILLISECOND),PHP_EOL;echo'所有时间S:',$c->getElapsedTime(HRTime\Unit::SECOND),PHP_EOL;//所有时间NS:14083898//所有时间US:14083.898//所有时间MS:14.083898//所有时间S:0.014083898echo'所有报价:',$c->getElapsedTicks(),PHP_EOL;//AllTicks:14083898在这段代码中,我们在两个计时测试代码中插入了一个循环测试代码,它不会被计入计时数据中。然后,我们restart()开始新的计时,最后通过getElapsedTime()和getElapsedTicks()得到总的计时时间。可以看出,上面的6929888加上这次的7154010,正好是14083898。中间不在定时器中的循环代码,不计入总的定时时间。总结是不是很有意思?它的功能和我们体育老师用的秒表一模一样。老师的秒表也可以通过多次按下来记录从第一个到最后一个的所有运行结果,最后还有一个总时间,而在代码中我们在做完全一样的操作。这个扩展对于精细的性能调试非常有用,也可以针对一些需要这种高精度时间差的业务开发。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/3。学习PHP高精度定时器HRTime扩展。PHP参考文档:https://www.php.net/manual/zh/book.hrtime.phphttps://www.cnblogs.com/chezxiaoqiang/archive/2012/03/23/2674386.html各媒体平台均可搜索【硬核项目经理】