你不知道的 PHP 缓存技巧
前言
相信有一定开发经验的PHP程序员都有缓存的使用经验,包括但不限于redis缓存,模板缓存,路由缓存,配置缓存,数据库缓存,还有opcache(真的很有用),但是今天我不准备炒冷饭了,我要讲点你不知道的缓存。
文档链接
- php源代码
- php扩展电子书
-
分析
首先为了说明问题,我贴出公司的一段代码,我相信你肯定写过,非常简单,就像下面这样。
$year = date('Y', time()); $month = date('m', time());
初看起来,好像没有什么问题,对头,你说的没错,代码是没有问题的,那么问题出在哪里呢?要解释这个问题,我要先给大家讲解下有关知识点,听好咯。
PHP函数
php自带的函数,是怎么运行的呢?很简单,php自带的函数都对应底层的一个C语言函数(关于PHP扩展以后会讲到),就以当前的time函数为例。
所有的PHP对应的底层函数,都是这么定义的,PHP_FUNCTION是C语言的一个宏定义,我们看看这个函数,它调用了函数php_time,那么php_time又是啥呢?
这里它调用了系统调用time,什么是系统调用?简单来说,系统调用就是操作系统提供给用户程序访问计算机资源的接口,更要命的是,系统调用极其耗时,说到这里你应该明白了,当你在php脚本里面每一次调用time(),php程序就会系统调用一次。
优化
刚才以time()函数作为例子分析了弊端,那么我们怎么来优化呢?其实很简单,对于时间要求不是那么严格的情况下,我们可以把时间缓存起来,就像下面这样。
class TimeWrapper
{
private static $now_time = 0;
/**
* @param bool $force_refresh 是否强制刷新
* @return int
*/
public static function getTime($force_refresh = false)
{
if ($force_refresh) {
self::$now_time = time();
} else {
if (!self::$now_time) {
self::$now_time = time();
}
}
return self::$now_time;
}
}
定义一个类,然后定义一个静态字段,就完事儿了。
疑惑
你可能会说,我的程序不在乎这么点儿时间。但是php自带的很多函数都会调用系统调用,结果不用我说,你应该也明白了。
本作品采用《CC 协议》,转载必须注明作者和本文链接
直接 $time = time(); 不就行拉
这样子,你反而获得不到真正的当前时间!!!
获得的只是缓存时候的时间
若要这样,何不直接 $_SERVER['REQUEST_TIME']
老哥,测试了吗?我亲测 false,时间貌似更久了~~
这种的话在队列中或者一些长连接中就有问题,队列不重启你的静态变量就不释放
学过单例模式的同学应该都觉得很熟悉,就laravel的auth里面就有结构一样的代码。
感谢你的输出,大家都晓得,哈哈。
然后他们说的这个时间缓存是没问题的,因为大部分项目都是fpm模式,且业务对时间要求不高,这个函数还是有作用。
和单例模式获取实例是一个理,不过这样写会不会简洁些?
膜拜大佬
膜拜大佬+1
这是啥? 直接下面不行吗? :sweat_smile:
缓存思路是好的,但是这个例子举得不好。
gettimeofday
系统调用是通过vDSO
提供的,调用是不需要进入内核态的上面这两点,就导致了Linux下
time()
其实会比TimeWrapper::getTime()
更快。Nginx和PHP的性能场景是不同的~
提到《深入linux内核架构》,视野挺广的
佩服这种注释