Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PHP の GC の話

11,627 views

Published on

第 87 回 PHP 勉強会での発表資料です。PHP の処理系に採用されている参照カウント方式の GC と循環参照を回収するアルゴリズムについて簡単に説明します。また、特定の限られた状況で循環参照の回収が処理速度に悪影響を与えることを、簡単なサンプルプログラムを用いて示します。

Published in: Technology
  • Be the first to comment

PHP の GC の話

  1. 1. PHP の GC の話 2015/02/27 第87回PHP勉強会
  2. 2. なぜ GC の話を? 言語処理系の実装を知るのは良い勉強になる GC はとても面白い ◦ 巧妙なアルゴリズム ◦ 高速化のための実装上の (低水準な) 工夫 両方まとめて楽しめる。しかも「本物の」コードで 2015/02/27 第87回 PHP 勉強会 2
  3. 3. なぜ GC の話を? 言語処理系の実装を知るのは良い勉強になる GC はとても面白い ◦ 巧妙なアルゴリズム ◦ 高速化のための実装上の (低水準な) 工夫 両方まとめて楽しめる。しかも「本物の」コードで 今日はこちらの話を中心に・・・ 2015/02/27 第87回 PHP 勉強会 3
  4. 4. 自己紹介 内山 雄司 ◦ 株式会社ピコラボ ◦ @y__uti ◦ http://y-uti.hatenablog.jp 好きな話題 ◦ 機械学習とその周辺分野(ほぼ仕事) ◦ 楽しいけれど数学は不真面目だったので色々つらい ◦ プログラミング言語処理系(学生のときの研究分野/今は趣味) ◦ 去年あたり?から HHVM とか PHP7 とか盛り上がっていて楽しい ◦ PHP dis 2015/02/27 第87回 PHP 勉強会 4
  5. 5. 目次 GC って何? GC の仕組み 循環参照を持つゴミの回収 gc_disable() の話 2015/02/27 第87回 PHP 勉強会 5
  6. 6. GC って何? 2015/02/27 第87回 PHP 勉強会 6
  7. 7. Wikipedia によると・・・ ガベージコレクション (garbage collection; GC) とは、 プログラムが動的に確保したメモリ領域のうち、不要になった領 域を自動的に解放する機能 である。 2015/02/27 第87回 PHP 勉強会 7 http://ja.wikipedia.org/wiki/ガベージコレクション
  8. 8. memory_limit PHP のスクリプトが使えるメモリの上限 2015/02/27 第87回 PHP 勉強会 8 $ cat php.ini ... ; Maximum amount of memory a script may consume (128MB) ; http://php.net/memory-limit memory_limit = 128M ...
  9. 9. メモリ不足のプログラム 128M を使いきってしまうと? 2015/02/27 第87回 PHP 勉強会 9 <?php $a1 = range(1, 200000); echo '1'; $a2 = range(1, 200000); echo '2'; $a3 = range(1, 200000); echo '3'; $a4 = range(1, 200000); echo '4'; $a5 = range(1, 200000); echo '5'; 見慣れた?エラー 1234PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in ... on line 6
  10. 10. プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 10 memory_limit = 128M
  11. 11. array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 11
  12. 12. array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 12 $a1
  13. 13. array(1, 2, ..., 200000) array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 13 $a1
  14. 14. array(1, 2, ..., 200000) array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 14 $a1 $a2
  15. 15. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 15 $a1 $a2 $a3
  16. 16. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 16 $a1 $a2 $a3 $a4
  17. 17. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 17 $a1 $a2 $a3 $a4
  18. 18. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) プログラム実行の様子 2015/02/27 第87回 PHP 勉強会 18 $a1 $a2 $a3 $a4 PHP Fatal Error
  19. 19. 変更版のプログラム 同じ変数 $a1 に代入する 2015/02/27 第87回 PHP 勉強会 19 <?php $a1 = range(1, 200000); echo '1'; $a1 = range(1, 200000); echo '2'; $a1 = range(1, 200000); echo '3'; $a1 = range(1, 200000); echo '4'; $a1 = range(1, 200000); echo '5'; これはメモリ不足にならず実行できる 12345 どうして実行できるの? ◦ PHP には「ごみ集め」 (Garbage Collection) の仕組みがあるから
  20. 20. PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 20 memory_limit = 128M
  21. 21. array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 21
  22. 22. array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 22 $a1
  23. 23. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 23 $a1
  24. 24. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 24 $a1
  25. 25. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 25 $a1
  26. 26. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 26 $a1
  27. 27. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 27 $a1
  28. 28. array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP に GC がなかったら 2015/02/27 第87回 PHP 勉強会 28 $a1 PHP Fatal Error
  29. 29. PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 29 memory_limit = 128M
  30. 30. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 30 $a1
  31. 31. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 31 $a1 ←もう使わない
  32. 32. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 32 $a1
  33. 33. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 33 $a1 ←もう使わない
  34. 34. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 34 $a1
  35. 35. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 35 $a1 ←もう使わない
  36. 36. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 36 $a1
  37. 37. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 37 $a1 ←もう使わない
  38. 38. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 38 $a1
  39. 39. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 39 $a1 ←もう使わない
  40. 40. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 40 $a1
  41. 41. array(1, 2, ..., 200000) array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 41 $a1 ←もう使わない
  42. 42. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 42 $a1
  43. 43. array(1, 2, ..., 200000) PHP には GC があるので 2015/02/27 第87回 PHP 勉強会 43 $a1 Happy!
  44. 44. GC の仕組み 2015/02/27 第87回 PHP 勉強会 44
  45. 45. GC の基本 「もう使わない」ことをどのように知るのか? 2015/02/27 第87回 PHP 勉強会 45 <?php $a1 = range(1, 200000); array(1, 2, ..., 200000) $a1 問題:10000 を表示するには? echo $a1[9999]; // 10000
  46. 46. GC の基本 「もう使わない」ことをどのように知るのか? 2015/02/27 第87回 PHP 勉強会 46 <?php $a1 = range(1, 200000); $a1 = range(200001, 400000); array(200001, ..., 400000) array(1, 2, ..., 200000) $a1 問題:10000 を表示するには? echo $a1[9999]; // 210000 ◦ 無理
  47. 47. GC の基本 「もう使わない」ことをどのように知るのか? ◦ とても難しい 「もう使えない」ことを知る ◦ わりと簡単 ◦ 辿れないものは使えない 2015/02/27 第87回 PHP 勉強会 47 array(200001, ..., 400000) array(1, 2, ..., 200000) $a1
  48. 48. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 48
  49. 49. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 49 $a1 = new MyList(); 1$a1
  50. 50. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 50 $a1->next = new MyList(); 1$a1 1
  51. 51. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 51 $a1->next->next = new MyList(); 1$a1 1 1
  52. 52. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 52 $a2 = new MyList(); 1$a1 1 $a2 1 1
  53. 53. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 53 $a2->next = $a1->next; 1$a1 2 $a2 1 1
  54. 54. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 54 $a1->next->next->next = new MyList(); 1$a1 2 $a2 1 11
  55. 55. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 55 $a1->next->next->next->next = $a1->next->next->next; 1$a1 2 $a2 2 11
  56. 56. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 56 $a2 = new MyList(); 1$a1 2 $a2 2 10 1
  57. 57. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 57 $a1 = new MyList(); 1$a1 1 $a2 2 1 1
  58. 58. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 58 unset($a1); 0 1 $a2 2 1 1
  59. 59. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 59 unset($a1); 0 $a2 2 1 1
  60. 60. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 60 unset($a1); $a2 1 1 1
  61. 61. PHP の GC 参照カウント方式 ◦ 自分に入ってくる矢印 (= 参照) の数を記録しておく ◦ 矢印の数が 0 になったら「もう使えない」 2015/02/27 第87回 PHP 勉強会 61 unset($a1); $a2 1 1 1 これは?→
  62. 62. 循環参照を持つごみの回収 2015/02/27 第87回 PHP 勉強会 62
  63. 63. 循環参照 参照カウント方式の弱点 ◦ 参照関係に循環があると矢印の数が 0 にならないまま辿れなくなる ◦ だんだん溜まっていき最後にはメモリ不足になってしまう PHP 5.2 まで ◦ 辿れなくなる前に自分で unset しなければいけなかった ◦ つらい・・・普通バグる 2015/02/27 第87回 PHP 勉強会 63 $a2 1 1 1
  64. 64. 循環参照の GC PHP 5.3 以降 ◦ 循環参照の問題にも対応 文献 ◦ Concurrent Cycle Collection in Reference Counted Systems ◦ http://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf ◦ http://www.ibm.com/ にアクセスして論文名でサイト内検索すれば見つかる 2015/02/27 第87回 PHP 勉強会 64 http://php.net/manual/ja/features.gc.collecting-cycles.php
  65. 65. 循環参照の GC PHP 5.3 以降 ◦ 循環参照の問題にも対応 たとえば以下の状態から・・・ 2015/02/27 第87回 PHP 勉強会 65 1$a1 $a2 2 2 1 1 1 2 2 2
  66. 66. 循環参照の GC - Release 参照カウントが 0 になった場合 ◦ ゴミなので回収する(通常の参照カウント方式) 2015/02/27 第87回 PHP 勉強会 66 unset($a1); 0 $a2 2 2 1 1 1 2 2 2
  67. 67. 循環参照の GC - PossibleRoot 参照カウントが減ったがまだ 0 ではない場合 ◦ ゴミができてしまった「かもしれない」 ◦ 候補として覚えておく 2015/02/27 第87回 PHP 勉強会 67 $a2 1 2 1 1 1 2 2 2 やばい奴ら
  68. 68. 循環参照の GC 必要に応じて候補をチェックする ◦ メモリ不足になった ◦ gc_collect_cycles() が呼ばれた ◦ 覚えきれなくなった (上限 10,000) 2015/02/27 第87回 PHP 勉強会 68 $a2 1 2 1 1 1 2 2 2 やばい奴ら
  69. 69. 循環参照の GC はじめに ◦ この図の全体を見渡すと・・・ 2015/02/27 第87回 PHP 勉強会 69 $a2 1 2 1 1 1 2 2 2 やばい奴ら ここはゴミ→
  70. 70. 循環参照の GC - MarkRoots 候補のオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 70 $a2 1 2 1 1 1 2 2 2 やばい奴ら
  71. 71. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 71 $a2 1 2 1 0 1 2 2 2 やばい奴ら
  72. 72. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 72 $a2 1 2 1 0 1 1 2 2 やばい奴ら
  73. 73. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 73 $a2 1 2 1 0 1 1 1 2 やばい奴ら
  74. 74. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 74 $a2 1 2 1 0 1 0 1 2 やばい奴ら
  75. 75. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 75 $a2 1 2 1 0 1 0 1 1 やばい奴ら
  76. 76. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 76 $a2 1 2 1 0 1 0 0 1 やばい奴ら
  77. 77. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 77 $a2 1 2 1 0 0 0 0 1 やばい奴ら
  78. 78. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 78 $a2 1 1 1 0 0 0 0 1 やばい奴ら
  79. 79. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 79 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  80. 80. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 80 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  81. 81. 循環参照の GC - MarkGray 今の状態 ◦ 候補から到達できるオブジェクトは灰色 ◦ 灰色以外からの参照のみカウント 2015/02/27 第87回 PHP 勉強会 81 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  82. 82. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 82 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  83. 83. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 83 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  84. 84. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 84 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  85. 85. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 85 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  86. 86. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ 2015/02/27 第87回 PHP 勉強会 86 $a2 0 0 1 0 0 0 0 1 やばい奴ら
  87. 87. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 87 $a2 0 0 1 0 0 0 1 1 やばい奴ら
  88. 88. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 88 $a2 0 0 1 0 0 1 1 1 やばい奴ら
  89. 89. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 89 $a2 0 0 1 0 0 1 2 1 やばい奴ら
  90. 90. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 90 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  91. 91. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 91 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  92. 92. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 92 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  93. 93. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 93 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  94. 94. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 94 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  95. 95. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 95 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  96. 96. 循環参照の GC - Scan 今の状態 ◦ 到達できるオブジェクトは黒 ◦ 到達できないオブジェクトは白 2015/02/27 第87回 PHP 勉強会 96 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  97. 97. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 97 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  98. 98. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 98 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  99. 99. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 99 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  100. 100. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 100 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  101. 101. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 101 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  102. 102. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 102 $a2 0 0 1 0 0 1 2 2 やばい奴ら
  103. 103. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 103 $a2 0 1 0 0 1 2 2 やばい奴ら
  104. 104. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 104 $a2 0 1 0 1 2 2 やばい奴ら
  105. 105. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 105 $a2 0 1 1 2 2 やばい奴ら
  106. 106. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 106 $a2 0 1 1 2 2 やばい奴ら
  107. 107. 循環参照の GC - CollectWhite 矢印を辿りながら ◦ 「白」のオブジェクトを回収する 2015/02/27 第87回 PHP 勉強会 107 $a2 1 1 2 2 やばい奴ら
  108. 108. 循環参照の GC - CollectWhite 今の状態 ◦ 到達できるオブジェクトのみ残っている 2015/02/27 第87回 PHP 勉強会 108 $a2 1 1 2 2 やばい奴ら
  109. 109. gc_disable() の話 2015/02/27 第87回 PHP 勉強会 109
  110. 110. 循環参照の GC (再考) 最初の状態が以下だったとしたら・・・ 2015/02/27 第87回 PHP 勉強会 110 1$a1 $a2 2 3 1 1 1 2 2 2
  111. 111. 循環参照の GC - Release 参照カウントが 0 になった場合 ◦ ゴミなので回収する(通常の参照カウント方式) 2015/02/27 第87回 PHP 勉強会 111 unset($a1); 0 $a2 2 3 1 1 1 2 2 2
  112. 112. 循環参照の GC - PossibleRoot 参照カウントが減ったがまだ 0 ではない場合 ◦ ゴミができてしまった「かもしれない」 ◦ 候補として覚えておく 2015/02/27 第87回 PHP 勉強会 112 $a2 1 3 1 1 1 2 2 2 やばい奴ら
  113. 113. 循環参照の GC - MarkRoots 候補のオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 113 $a2 1 3 1 1 1 2 2 2 やばい奴ら
  114. 114. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 114 $a2 1 3 1 0 1 2 2 2 やばい奴ら
  115. 115. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 115 $a2 1 3 1 0 1 1 2 2 やばい奴ら
  116. 116. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 116 $a2 1 3 1 0 1 1 1 2 やばい奴ら
  117. 117. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 117 $a2 1 3 1 0 1 0 1 2 やばい奴ら
  118. 118. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 118 $a2 1 3 1 0 1 0 1 1 やばい奴ら
  119. 119. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 119 $a2 1 3 1 0 1 0 0 1 やばい奴ら
  120. 120. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 120 $a2 1 3 1 0 0 0 0 1 やばい奴ら
  121. 121. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 121 $a2 1 2 1 0 0 0 0 1 やばい奴ら
  122. 122. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 122 $a2 0 2 1 0 0 0 0 1 やばい奴ら
  123. 123. 循環参照の GC - MarkGray 矢印を辿りながら ◦ 参照カウントを 1 減らす ◦ 辿ったオブジェクトを「灰色」にする 2015/02/27 第87回 PHP 勉強会 123 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  124. 124. 循環参照の GC - MarkGray 今の状態 ◦ 候補から到達できるオブジェクトは灰色 ◦ 灰色以外からの参照のみカウント 2015/02/27 第87回 PHP 勉強会 124 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  125. 125. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 125 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  126. 126. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 126 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  127. 127. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 127 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  128. 128. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする 2015/02/27 第87回 PHP 勉強会 128 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  129. 129. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ 2015/02/27 第87回 PHP 勉強会 129 $a2 0 1 1 0 0 0 0 1 やばい奴ら
  130. 130. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 130 $a2 0 1 1 0 0 0 1 1 やばい奴ら
  131. 131. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 131 $a2 0 1 1 0 0 1 1 1 やばい奴ら
  132. 132. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 132 $a2 0 1 1 0 0 1 2 1 やばい奴ら
  133. 133. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 133 $a2 0 1 1 0 0 1 2 2 やばい奴ら
  134. 134. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 134 $a2 0 1 1 0 0 1 2 2 やばい奴ら
  135. 135. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 135 $a2 0 1 1 0 0 1 2 2 やばい奴ら
  136. 136. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 136 $a2 0 1 1 0 0 1 2 2 やばい奴ら
  137. 137. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 137 $a2 1 1 1 0 0 1 2 2 やばい奴ら
  138. 138. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 138 $a2 1 1 1 1 0 1 2 2 やばい奴ら
  139. 139. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 139 $a2 1 1 1 1 0 2 2 2 やばい奴ら
  140. 140. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 140 $a2 1 1 1 1 1 2 2 2 やばい奴ら
  141. 141. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 141 $a2 1 2 1 1 1 2 2 2 やばい奴ら
  142. 142. 循環参照の GC - ScanBlack 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 142 $a2 1 3 1 1 1 2 2 2 やばい奴ら
  143. 143. 循環参照の GC - Scan 矢印を辿りながら ◦ 参照カウントが 0 なら「白」にする ◦ 1 以上なら「黒」にして・・・ ◦ 減らしてしまった参照カウントを戻していく 2015/02/27 第87回 PHP 勉強会 143 $a2 1 3 1 1 1 2 2 2 やばい奴ら
  144. 144. 循環参照の GC ゴミなど一つも無かった ◦ 時間の無駄 2015/02/27 第87回 PHP 勉強会 144 $a2 1 3 1 1 1 2 2 2 やばい奴ら
  145. 145. ところで 2015/02/27 第87回 PHP 勉強会 145
  146. 146. ゴミの候補はいつできる? 関数を呼ぶだけでゴミの候補が増える (引数の型による) 2015/02/27 第87回 PHP 勉強会 146 <?php $a = new MyList(); function doSomething($foo) {} doSomething($a);
  147. 147. ゴミの候補はいつできる? 関数を呼ぶだけでゴミの候補が増える (引数の型による) 2015/02/27 第87回 PHP 勉強会 147 <?php $a = new MyList(); function doSomething($foo) {} doSomething($a); $a 1 ◦ doSomething 実行前
  148. 148. ゴミの候補はいつできる? 関数を呼ぶだけでゴミの候補が増える (引数の型による) 2015/02/27 第87回 PHP 勉強会 148 <?php $a = new MyList(); function doSomething($foo) {} doSomething($a); $a 2 $foo ◦ doSomething 実行中
  149. 149. ゴミの候補はいつできる? 関数を呼ぶだけでゴミの候補が増える (引数の型による) 2015/02/27 第87回 PHP 勉強会 149 <?php $a = new MyList(); function doSomething($foo) {} doSomething($a); $a 1 ◦ doSomething 実行後
  150. 150. gc_disable() の使いどころ 原則 ◦ 普通は gc_disable() なんて考えなくてよい ◦ メモリリークの元 次のようなプログラムは検討の余地あり ◦ 巨大なグラフ (or 木, リスト, ...) を辿りながら処理する ◦ そのグラフは循環参照によるゴミを出さない 2015/02/27 第87回 PHP 勉強会 150
  151. 151. 実験 こんなデータ構造を作って各要素を引数に関数を呼ぶ 2015/02/27 第87回 PHP 勉強会 151 1 ・・・ 1 1 ・・・ 1 1 1 ・・・ ・・・ 配列 リスト
  152. 152. 実験 こんなデータ構造を作って各要素を引数に関数を呼ぶ 2015/02/27 第87回 PHP 勉強会 152 1 ・・・ 1 1 ・・・ 1 1 1 ・・・ ・・・ 配列 リスト 配列の要素数によって循環参照の GC が 発生したり発生しなかったりする
  153. 153. 実験 プログラム (データ構造を組み立てる部分は省略) 2015/02/27 第87回 PHP 勉強会 153 ... gc_collect_cycles(); $start = microtime(true); for ($i = 0; $i < 10; ++$i) { foreach ($arrayOfList as $list) { doSomething($list); // doSomething は空の関数 } } $end = microtime(true); ◦ $arrayOfList の要素数を変更しながら ($end - $start) を計測 ◦ $list の長さは固定 (100 とした)
  154. 154. 実験結果 2015/02/27 第87回 PHP 勉強会 154 PHP 5.6.5 との比較 memory_limit=1024M として実験 Core i5-3337U 1.80GHz
  155. 155. 実験結果 2015/02/27 第87回 PHP 勉強会 155 PHP 7.0.0 との比較 memory_limit=1024M として実験 Core i5-3337U 1.80GHz
  156. 156. おわり ありがとうございました 2015/02/27 第87回 PHP 勉強会 156

×