APC缓存简介
APC全称是Alternative PHP Cache官方翻译叫可选PHP缓存它为我们提供了缓存和优化PHP的中间代码的框架 APC的缓存分两部分系统缓存和用户数据缓存
系统缓存
它是指APC把PHP文件源码的编译结果缓存起来然后在每次调用时先对比时间标记如果未过期则使用缓存的中间代码运行默认缓存s(一小时)但是这样仍会浪费大量CPU时间因此可以在phpini中设置system缓存为永不过期(l=)不过如果这样设置改运php代码后需要重启WEB服务器目前使用较多的是指此类缓存
用户数据缓存
缓存由用户在编写PHP代码时用apc_store和apc_fetch函数操作读取写入的如果数据量不大的话可以一试如果数据量大使用类似memcache此类的更加专着的内存缓存方案会更好
缓存key生成规则
APC的缓存中的每个slot都会有一个keykey是apc_cache_key_t结构体类型除了key相关的属性关键是h字段的生成 h字段决定了此元素落于slots数组的哪一个位置对于用户缓存和系统缓存其生成规则不同 用户缓存通过apc_cache_make_user_key函数生成key通过用户传递进来的key字符串依赖PHP内核中的hash函数(PHP的hashtable所使用的hash函数zend_inline_hash_func)生成h值
系统缓存通过apc_cache_make_file_key函数生成key通过APC的配置项apcstat的开关来区别对待不同的方案在打开的情况下即apcstat= On 时如果被更新则自动重新编译和缓存编译后的内容此时的h值是文件的device和inode相加所得的值在关闭的情况下即apcstat=off时当文件被修改后如果要使更新的内容生效则必须重启Web服务器此时h值是根据文件的路径地址生成并且这里的路径是绝对路径即使你是使用的相对路径也会查找PG(include_path)定位文件以取得绝对路径所以使用绝对路径会跳过检查可以提高代码的效率
添加缓存过程
以用户缓存为例apc_add函数用于给APC缓存中添加内容如果key参数为字符串中APC会根据此字符串生成key如果key参数为数组APC会遍历整个数组生成key根据这些keyAPC会调用_apc_store将值存储到缓存中由于这是用户缓存当前使用的缓存为apc_user_cache执行写入操作的是apc_cache_make_user_entry函数其最终调用apc_cache_user_insert执行遍历查询和写入操作与此对应系统缓存使用apc_cache_insert执行写入操作其最终都会调用_apc_cache_insert
不管是用户缓存还是系统缓存大体的执行过程类似步骤如下
通过求余操作定位当前key的在slots数组中的位置 cache>slots[keyh % cache>num_slots];
在定位到slots数组中的位置后遍历当前key对应的slot链表如果存在slot的key和要写入的key匹配或slot过期清除当前slot
在最后一个slot的后面插入新的slot
APC模块安装
WINDOWS
第一步下载php_apcdll 在//package/apc 要与php版本对应 将php_apcdll放入你的ext目录
第二步让phpini支持apc扩展模块 然后打开phpini 加入
extension=php_apcdll
apcrfc = on
apcmax_file_size = M
upload_max_filesize = M
post_max_size = M
//以上参数可自己定义
第三步检查是否支持PHP APC apc_store apc_fetch PHP APC 配置参数 把相关的配置放在一起解释
apcenabled= apcenabled默认值是你可设成禁用APC如果你设置为的时候同样把extension=apcso也注释掉(这样可以节约内存资源)一旦启用了APC功能则会缓存Opcodes到共享内存
apcshm_segments =
总结 使用Spinlocks锁机制能够达到最佳性能
APC提供了apcphp用于监控与管理APC缓存不要忘记修改管理员名和密码
APC默认通过mmap匿名映射创建共享内存缓存对象都存放在这块大型的内存空间由APC自行管理该共享内存
我们需要通过统计调整apcshm_sizeapcnum_files_hintsapcuser_entries_hint的值直到最佳
好吧我承认apcstat = 可以获得更佳的性能要我做什么都可以接受
PHP预定义常量可以使用apc_define_constants()函数不过据APC开发者介绍说pecl hidef性能更佳抛异define吧它是低效的
函数apc_store()对于系统设置等PHP变量生命周期是整个应用(从httpd守护进程直到httpd守护进程关闭)使用APC比Memcached会更好必竟不要经过网络传输协议tcp
APC不适于通过函数apc_store()缓存频繁变更的用户数据会出现一些奇异现象
LIUNX
wget /get/APCtgz
tar zxvf APCtgz cd APC
/usr/local/php/bin/phpize
/configure enableapc enablemmap enableapcspinlocks disableapcpthreadmutex withphpconfig=/usr/local/php/bin/phpconfig
make
sudo make install
在/usr/local/php/etc/phpini 加入
extension = apcso ;
;APC setting
apcenabled =
apcshm_segments =
apcshm_size = M
apcoptimization =
apcnum_files_hint =
l =
apcgc_ttl =
apccache_by_default = on
重启apache 或者 /usr/local/php/sbin/phpfpm restart
查看phpinfo apc
下面引用框架的APC缓存类
initphp框架之APC缓存类
[php]
<?php
if (!defined(IS_INITPHP)) exit(Access Denied!)
/*********************************************************************************
* InitPHP 国产PHP开发框架 DaoAPC缓存 不适合频繁写入的缓存数据
*
* 版权所有 CopyRight By
* 您可以自由使用该源码但是在使用过程中请保留作者信息尊重他人劳动成果就是尊重自己
*
* $Author:zhuli
* $Dtime:
***********************************************************************************/
class apcInit {
/**
* Apc缓存设置缓存
* 设置缓存keyvalue和缓存时间
* @param string $key KEY值
* @param string $value 值
* @param string $time 缓存时间
*/
public function set_cache($key $value $time = ) {
if ($time == ) $time = null; //null情况下永久缓存
return apc_store($key $value $time)
}
/**
* Apc缓存获取缓存
* 通过KEY获取缓存数据
* @param string $key KEY值
*/
public function get_cache($key) {
return apc_fetch($key)
}
/**
* Apc缓存清除一个缓存
* 从memcache中删除一条缓存
* @param string $key KEY值
*/
public function clear($key) {
return apc_delete($key)
}
/**
* Apc缓存清空所有缓存
* 不建议使用该功能
* @return
*/
public function clear_all() {
apc_clear_cache(user) //清除用户缓存
return apc_clear_cache() //清楚缓存
}
/**
* 检查APC缓存是否存在
* @param string $key KEY值
*/
public function exists($key) {
return apc_exists($key)
}
/**
* 字段自增用于记数
* @param string $key KEY值
* @param int $step 新增的step值
*/
public function inc($key $step) {
return apc_inc($key (int) $step)
}
/**
* 字段自减用于记数
* @param string $key KEY值
* @param int $step 新增的step值
*/
public function dec($key $step) {
return apc_dec($key (int) $step)
}
/**
* 返回APC缓存信息
*/
public function info() {
return apc_cache_info()
}
}