Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
PHP の GC の話 | PDF
[go: Go Back, main page]

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

PHP の GC の話

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