Zend OPcacheの速さの秘密を探る

Preview:

Citation preview

Zend OPcacheの速さの秘密を探る

hnwPHPカンファレンス2013(2013/09/14) 発表資料

13年9月14日土曜日

自己紹介

@hnw / id:hnw

勤務先:KLab株式会社

社内PHP案件の助っ人など(性能改善とか)やってます

カレーとバグが大好物

おいしい情報をお待ちしています

13年9月14日土曜日

今日おはなしすること

Zend OPcache とは

最適化フェーズの内側

安定性をどう判断するか

13年9月14日土曜日

Zend OPcache とは

最適化フェーズの内側

安定性をどう判断するか

13年9月14日土曜日

Zend OPcache とは

PHPのopcodeキャッシュ&最適化エクステンション

PHP 5.5に標準添付、APCの代替として期待されている

PHP 5.2から5.5に対応

前身: Zend社の商用製品(Zend Optimizer)

2013年2月 Open Source化、名前も変わった

13年9月14日土曜日

APC との違い

KVS 機能が無い

APCu などを併用しましょう

バイトコードの最適化を行う

これが速さの秘密

13年9月14日土曜日

Zend OPcache の性能

ベンチマークテスト

Opcode Cache Benchmarks

全般的にAPCより速い

仕組み上も有利

APCより遅くなる状況が珍しい

13年9月14日土曜日

OPcacheが行う「最適化」って何?

13年9月14日土曜日

素のPHPの処理PHPコードをopcodeに変換してからVM実行している

Parser

Lexer

Opcode Compiler

Zend VM

PHP

token

AST

opcode

13年9月14日土曜日

素のPHPの処理PHPコードをopcodeに変換してからVM実行している

Parser

Lexer

Opcode Compiler

Zend VM

PHP

token

AST

opcode

13年9月14日土曜日

opcodeの例

参考:Opcode Descriptions and Examples

<?phpif (false) { echo ”*”;}

13年9月14日土曜日

素のPHPの処理PHPコードをopcodeに変換してからVM実行している

Parser

Lexer

Opcode Compiler

Zend VM

PHP

token

AST

opcode

13年9月14日土曜日

Zend VM概要

最大4オペランドのレジスタマシン

レジスタ数は無限個

各レジスタの変数型は実行時まで決定できない

命令数 146(PHP 5.5.3時点)

13年9月14日土曜日

PHP+APCの処理opcodeキャッシュにより、PHPの解釈をスキップできる

Parser

Lexer

Opcode Compiler

Zend VM

PHP

token

AST

opcode

Opcode Cacheopcode

13年9月14日土曜日

PHP+OPcacheの処理opcodeレベルの最適化処理を行い、キャッシュする

Parser

Lexer

Opcode Compiler

Zend VM

Optimizer

PHP

token

AST

opcode

opcode

Opcode Cacheopcode

13年9月14日土曜日

最適化の例opcode数を減らしたり、効率の良いものに置換したりする

OPcache無効:4opcodes

OPcache有効:1opcode13年9月14日土曜日

VLDopcodeを確認するためのPHP extension

http://derickrethans.nl/projects.html#vld

メンテナ:Derick Rethans

GitHub上ではPHP 5.5に対応済み

https://github.com/derickr/vld

5.5対応のパッチは僕が書きました。バグレポよろしく。

13年9月14日土曜日

Zend OPcache とは

最適化フェーズの内側

安定性をどう判断するか

13年9月14日土曜日

OPcacheの最適化内容substitute persistent constants (true, false, null, etc)perform compile-time evaluation of constant binary and unary operations

optimize series of ADD_STRING and/or ADD_CHAR

convert CAST(IS_BOOL,x) into BOOL(x)convert INTI_FCALL_BY_NAME + DO_FCALL_BY_NAME into DO_FCALL

convert non-numeric constants to numeric constants in numeric operatorsoptimize constant conditional JMPs

optimize static BRKs and CONTs

optimize $i = $i+expr to $i+=exproptimize series of JMPs

change $i++ to ++$i where possibleCFG optimization

Optimize temp variables usage

remove NOPs

高度な最適化は行っていない印象

13年9月14日土曜日

最適化の具体例(1)コンパイル時に評価できる場所は先に評価する

「$seconds_in_a_day = 60*60*24;」

あらかじめ 86400 として変数にセットする

13年9月14日土曜日

最適化の具体例(1)OPcacheなし

60を60倍して、さらに24倍している

13年9月14日土曜日

最適化の具体例(1)OPcacheあり

60*60*24した結果をいきなり変数に代入

13年9月14日土曜日

最適化の具体例(2)可能であれば $i++ を ++$i に変える

式 $i++ の結果を利用していない場合、両者は交換可能

交換するとopcode数が減る

$i++ はZend VM上では2命令に展開される

++$i は1命令に展開される

13年9月14日土曜日

最適化の具体例(3)無駄なジャンプ命令を削除する

ジャンプ命令の飛び先がジャンプ命令になる場合がある

2重ループの終端など

<?phpfor ($i = 0; $i < 10; $i++) { for ($j = 0; $j < 10; $j++) { $sum += $arr[$i][$j] }}

13年9月14日土曜日

OPcacheがやらないこと(1)

共通部分式の除去 (Common Subexpression Elimination)

下記コードには「$_GET[’x’]」が2回出現

opcodeレベルでは3命令、一時変数に格納すれば有利

<?php$y = $_GET[’x’] + 1;$z = $_GET[’x’] - 9;

13年9月14日土曜日

OPcacheがやらないこと(2)

ループ不変式の追い出し (Loop Invariant Motion)

可能であればループ内の式をループ外に追い出す

例:下記の「$a=$b*$c」をループ外に追い出す

<?phpfor ($i = 0; $i < 10; $i++) { $a = $b * $c; ...($a,$b,$cの値がループ内で不変)

}

13年9月14日土曜日

最適化の効果ひとつひとつの最適化の効果はごく僅か

この手の最適化は「ちりも積もれば」的な部分が大きい

人力で行っても報われないことが多い

細かい最適化が好きな人はOPcacheに機能追加しよう!

教科書的な内容で未実装のものが多い

13年9月14日土曜日

Zend OPcache とは

最適化フェーズの内側

安定性をどう判断するか

13年9月14日土曜日

APCとの比較

PHP 5.4用のAPCはずっとbeta

高負荷サイトでのホットデプロイ時に白画面になる事故

OPcache はPHP 5.5から本体添付、5.5なら鉄板

PHP 5.2以降をサポートしている

PHP 5.4との組み合わせも要注目

13年9月14日土曜日

OPcacheの枯れ具合

一定の安心感

開発開始から約10年、Zend社の製品として提供

PHPのコアコミッターが複数人参加している

今までソースコードが出ていなかった分、ポカがありうる

最近バグ報告しました / PHP5.5.2 に入ってます

zendtech/ZendOptimizerPlus PR#113

13年9月14日土曜日

まとめOPcacheの最適化

仕組みとしても、実測値から見ても有効

まだ最適化の余地がある

OPcacheの安定性

APCより良いのでは(特に5.4+)

一定レベル以上ではないか

13年9月14日土曜日

ご静聴ありがとうございました

13年9月14日土曜日

Recommended