summaryrefslogtreecommitdiffhomepage
path: root/slides.md
blob: 74c56c6e40f00c07ca4fc348b7a8ecc9d3aceae1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# PHP 処理系の garbage collection を理解する
メモリはいつ解放されるのか






はじめに

メモリ

コンピュータの一時データ置き場


メモリの容量は増え続けている

無限ではない

使い果たすと...
プロセスの強制終了
極端なパフォーマンスの低下



メモリ管理

必要なメモリを確保する
不要なメモリを解放する


メモリの「確保」割り当て

このサイズのメモリが必要です


メモリの「解放」

ここのメモリは不要になりました



メモリ管理は難しい


メモリリーク
    解放すべきメモリ領域を解放していない
double free
    解放済みのメモリ領域をまた解放した
use-after-free
    解放済みのメモリ領域にアクセスした
buffer overflow
    確保したメモリ領域を越えてアクセスした



PHP でメモリ管理を直接おこなう必要はない



Garbage Collection (GC)

メモリ管理の自動化
自動でメモリを解放



PHP の GC



参照カウント + マークアンドスイープ




参照カウント

参照されている数を数える
ゼロになったら解放する



$a = ["foo"];
$b = ["bar"];
$a[] = $b;
unset($b);
unset($a);



参照カウントの利点

未使用オブジェクトが即座に解放される
解放にかかるコストが全体に分散する


参照カウントの欠点

参照の追加にコストがかかる
マルチスレッド環境に向かない
循環参照を扱えない



$a = new stdClass();
$b = new stdClass();
$a->x = $b;
$b->x = $a;



$a = new stdClass();
$b = new stdClass();
$a->x = $b;
$b->x = $a;
unset($b);
unset($a);




参照カウントでは循環参照を解放できない



マークアンドスイープ (mark & sweep)

循環参照の解放のみ担う


最も基本的なマークアンドスイープ
PHP のマークアンドスイープ



マークフェーズ
スイープフェーズ



マーク
    確実に使われているオブジェクト (ルート) に印を付ける
    そこから辿れるオブジェクトに印を付ける
スイープ
    全オブジェクトを調べて、印が付いていなければ解放する




図



PHP のマークアンドスイープ


ほとんどのオブジェクトは参照カウントで解放される
全オブジェクトを走査しなくていい


循環参照「かもしれない」オブジェクトを登録

refcount を減らしたときに 0 にならなかった




マーク
    循環参照かもしれないオブジェクトを root buffer へ登録
    root buffer から辿れるオブジェクトの refcount を 1減らす
スイープ
    すべての root buffer から辿れるオブジェクトについて、
    refcount = 0 なら解放する
    refcount > 0 なら refcount を1増やして root buffer から消す



図



PHP のマークアンドスイープ GC が呼ばれるタイミング

root buffer が一杯になったとき (デフォルトで 10,000)




PHP の GC

参照カウント + マークアンドスイープ

循環参照以外は参照カウントで、
循環参照はマークアンドスイープで解放



多くのオブジェクトは未使用になると即座に解放される
循環参照を形成しているオブジェクトは遅れて解放される

fclose() は明示的に呼ぶべきか?
常に呼ぶべき
呼ばなくても問題ないかを判定するのが困難
呼ばなくても問題ない状態を維持できるとは限らない




話せなかったこと

複数スレッド/プロセス間での共有
リクエスト毎に確保・解放されるメモリとグローバルなメモリ
Copy on Write
弱参照
memory_limit