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()
}
}
From:http://tw.wingwit.com/Article/program/PHP/201311/20804.html