PHPコアから読み解く定石の嘘ホント #phpcon2013

10,193 views

Published on

(PHPカンファレンス2013での講演内容です) 突然ですが…そのPHPの定石は正しいと言えるでしょうか?「echoの方がprintより速い」「エラー抑制演算子@は常に避けるべき」などなど、PHPを書く上で"定石"と呼ばれるコーディングスタイルがいくつもあります。それらの挙動をパフォーマンス計測とPHPの内部実装に踏み込みつつ、わかりやすく検証していきます。

Published in: Technology
0 Comments
22 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
10,193
On SlideShare
0
From Embeds
0
Number of Embeds
5,293
Actions
Shares
0
Downloads
16
Comments
0
Likes
22
Embeds 0
No embeds

No notes for slide

PHPコアから読み解く定石の嘘ホント #phpcon2013

  1. 1. PHPコアから読み解く 定石の嘘ホント ヤフー株式会社 蒋(蒋池) 東龍
  2. 2. 2 レジュメ • 前編(5分) – もろもろ始める前に • 中編(24分) – エラー制御演算子 – 比較演算子 – 標準出力 • 後編(1分) – おわり
  3. 3. 3 もろもろ始める前に PHP における定石を 何か知っていますか?
  4. 4. 4 もろもろ始める前に その定石は どのようにして 正しいと判断しましたか?
  5. 5. 5 もろもろ始める前に 定石とは何でしょうか?
  6. 6. 6 もろもろ始める前に デジタル大辞泉 より
  7. 7. 7 もろもろ始める前に 物事をするときの、 最上とされる方法・手順
  8. 8. 8 もろもろ始める前に つまり PHP の定石とは
  9. 9. 9 もろもろ始める前に PHP でコーディングする時の 最上とされる方法・手順
  10. 10. 10 もろもろ始める前に 定石の良し悪しは どうやって判断すれば よいのでしょうか?
  11. 11. 11 もろもろ始める前に 数字 および 論理から 判断する必要がある
  12. 12. 12 もろもろ始める前に 数字に関しては……
  13. 13. 13 もろもろ始める前に 実行時の 速度を計測する
  14. 14. 14 もろもろ始める前に コンパイルやネットワークを 計測しないようにするため 任意のコードを microtime() で挟む (単位は usec)
  15. 15. 15 もろもろ始める前に <?php $start = microtime(true); $max = <計測回数>; for($i = 0; $i < $max; $i++) { <該当処理> } $end = microtime(true); $tm = $end - $start; error_log("time[$tm]usec¥n"); //?>
  16. 16. 16 もろもろ始める前に 論理に関しては……
  17. 17. 17 もろもろ始める前に スクリプトの オペコードを解析する
  18. 18. 18 もろもろ始める前に 最小の命令単位である オペコードについて考えるため vld(Vulcan Logic Disassembler) でダンプする
  19. 19. 19 もろもろ始める前に <番号> <オペコード> <オペランド1> <オペランド2> ※オペコード=オペレーター=最小単位の処理 ※オペランド=引数 ※対応するハンドラは ZEND_*_HANDLER()
  20. 20. 20 もろもろ始める前に 答え(を覚えること)は 全く重要ではありません
  21. 21. 21 もろもろ始める前に どっちの方が速いのか どうしてそうなのか 考えてみることが重要!
  22. 22. 22 もろもろ始める前に ここからは クイズ形式です
  23. 23. 23 もろもろ始める前に 一人では寂しいので 双方向で進めさせてください!
  24. 24. 24 もろもろ始める前に 1問につき8分! 1. 出題(50秒) 2. 黙考(10秒) 3. 質問、挙手、指名(1分) 4. 回答(3分) 5. 考察(3分)
  25. 25. 25 エラー制御演算子 エラー制御演算子 なし vs あり どっちが速い? (100回計測)
  26. 26. 26 エラー制御演算子 for($i = 0; $i < $max; $i++) { include('nothing.php'); } ※nothing.phpは存在しない for($i = 0; $i < $max; $i++) { @include('nothing.php'); } ※nothing.phpは存在しない
  27. 27. 27 エラー制御演算子 あれこれ
  28. 28. 28 エラー制御演算子 0.088059902191162 usec 0.085351943969727 usec 速 い
  29. 29. 29 エラー制御演算子 11 INCLUDE_OR_EVAL 'nothing.php', INCLUDE 11 BEGIN_SILENCE 12 INCLUDE_OR_EVAL 'nothing.php', INCLUDE 13 END_SILENCE ~7
  30. 30. 30 エラー制御演算子 エラー制御演算子は一時的に error_reporting を 0 にしている エラーがあった時には 出力が減るので処理は速くなる
  31. 31. 31 比較演算子 比較演算子 ($a == $b) vs ($a === $b) どっちが速い? (10万回計測)
  32. 32. 32 比較演算子 $a = "1"; for($i = 0; $i < $max; $i++) { if(1 == $a){ // } } $a = "1"; for($i = 0; $i < $max; $i++) { if(1 === $a){ // } }
  33. 33. 33 比較演算子 あれこれ
  34. 34. 34 比較演算子 0.017616987228394 usec 0.0085439682006836 usec 速 い
  35. 35. 35 比較演算子 !2 = $a 11 IS_EQUAL 1, !2 !2 = $a 11 IS_IDENTICAL 1, !2
  36. 36. 36 比較演算子 オペランドの型が違う時 == の場合には型変換を試みるが === の場合には型変換を試みない 型が違う場合には === の方がずっと速い
  37. 37. 37 標準出力 標準出力 print() vs echo() どっちが速い? (1000回計測)
  38. 38. 38 標準出力 for($i = 0; $i < $max; $i++) { print("abcdefghijklmn opqrstuvwxyz¥n"); } ※実際には1行 for($i = 0; $i < $max; $i++) { echo("abcdefghijklmn opqrstuvwxyz¥n"); } ※実際には1行
  39. 39. 39 標準出力 あれこれ
  40. 40. 40 標準出力 0.00041317939758301 usec 0.00037407875061035 usec 速 い
  41. 41. 41 標準出力 10 PRINT 'abcdefghijklmn opqrstuvwxyz%0A’ (~6に結果) ※実際には1行 11 FREE ~6 10 ECHO 'abcdefghijklmn opqrstuvwxyz%0A’ ※実際には1行
  42. 42. 42 標準出力 異なるオペコードだが PRINT は ECHO を ラッピングしていて戻り値もある (必ず 1 が返る) echo() を利用した方がよい
  43. 43. 43 おわり 定石は 前提条件によって 全く姿を変えてしまう
  44. 44. 44 おわり だから
  45. 45. 45 おわり 定石は 使えることよりも 考えることの方が大切
  46. 46. 46 おわり さらには
  47. 47. 47 おわり ただ暗記するよりも 考えてみた方が 楽しいし覚えられる
  48. 48. 48 おわり • オペコード – http://blog.golemon.com/ • PHP コード最適化 Best Practices 63 – http://d.hatena.ne.jp/koto2/20080518/12 11070116
  49. 49. 49 おわり ありがとうございました

×