デフォルトではセッションはファイルに書き出されます。
ディスクI/Oはボトルネックなので、より早いメモリ保存にしてみます。
とりあえずWindows版PHP7にはAPCuが入ってないのでPECLから拾ってくる。
今回は1.0.3のDLLをダウンロード。
解凍したらextディレクトリにphp_apcu.dllを置いてphp.iniに以下を記載。
Linuxなら適当にpeclコマンドでも使って。
extension=php_apcu.dll
[APCu]
apc.enabled = 1
apc.entries_hint = 4096
apc.gc_ttl = 3600
apc.ttl = 3600
Apacheを再起動したらAPCu関数が使えるようになっているはず。
class MySessionHandler implements SessionHandlerInterface{
/**
* コンストラクタ
* @param string パス
* @param string session_name()
* @return bool true
*/
public function open($save_path, $name): bool {
return true;
}
/**
* デストラクタ
* @return bool true
*/
public function close(): bool {
return true;
}
/**
* session_destroy()した
* @param string session_id()
* @return bool true
*/
public function destroy($session_id): bool {
if(apcu_exists($session_id)){
return apcu_delete($session_id);
}
return true;
}
/**
* $_SESSIONを返す。
* @param string session_id()
* @return string session_encode($_SESSION)
*/
public function read($session_id): string {
return apcu_fetch($session_id);
}
/**
* $_SESSIONを保存する。
* @param string session_id()
* @param string session_encode($_SESSION)
* @return bool true
*/
public function write($session_id, $session_data): bool {
return apcu_store($session_id, $session_data, (int)ini_get('apc.ttl'));
}
/**
* ガベージコレクションが動いた。
* @param int session.gc_maxlifetime
* @return bool true
*/
public function gc($maxlifetime): bool {
$list = apcu_cache_info();
$ttl = (int)ini_get('apc.gc_ttl');
foreach($list['cache_list'] as $v){
if( ($v['access_time'] + $ttl) < $_SERVER['REQUEST_TIME']){
apcu_delete($v['info']);
}
}
return true;
}
}
// セッションハンドラ変更
session_set_save_handler(new MySessionHandler(), true);
// 以後セッションはメモリに保存される
session_start();
session_regenerate_id();
$a=session_id();
$_SESSION['a'] = 'b';
session_name()とか実装してないけど誰も使わないからいいよね。
gcは不要になったAPCuを削除しています。
apcu_store()は配列に値を入れるようなもので、ttlを越えると配列の値は取得できなくなりますが、配列のキー自体は残っています。
そのためキー自体を削除する処理が入っています。
APCUIteratorでは何故かオプションAPC_LIST_DELETEDを指定しても取得できませんでした。
しかしここはapc.ttl
とapc.gc_ttl
とsession.gc_maxlifetime
どれに従うべきなんだろうか。
さて、せっかく作ったはいいけど、大人数が使うサービスでやるとメモリ不足で死ぬし、少人数しかいないサービスではそもそもディスクアクセスでも十分な速度だから作る必要無いしで、需要がよくわからない。