summaryrefslogtreecommitdiffhomepage
path: root/slides.saty
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-02-04 01:20:34 +0900
committernsfisis <nsfisis@gmail.com>2025-02-22 07:11:04 +0900
commit6f93cab592ddf3b8e7c544bae489ebef63a091cc (patch)
tree9aa7dcf31d01c6dfda5bbd1c91e31f388649df0e /slides.saty
parentd1f630f6ba442c9f01a58bf56a06312be6c50166 (diff)
downloadphpcon-nagoya-2025-slides-6f93cab592ddf3b8e7c544bae489ebef63a091cc.tar.gz
phpcon-nagoya-2025-slides-6f93cab592ddf3b8e7c544bae489ebef63a091cc.tar.zst
phpcon-nagoya-2025-slides-6f93cab592ddf3b8e7c544bae489ebef63a091cc.zip
add slides
Diffstat (limited to 'slides.saty')
-rw-r--r--slides.saty789
1 files changed, 789 insertions, 0 deletions
diff --git a/slides.saty b/slides.saty
new file mode 100644
index 0000000..6a2ba7c
--- /dev/null
+++ b/slides.saty
@@ -0,0 +1,789 @@
+@import: ./slydifi/my-theme
+@require: code-printer/code-design
+@require: code-printer/code-printer
+@require: code-printer/code-syntax
+@require: code-printer/code-theme
+@require: figbox/figbox
+
+let ex-big-textbox ?:size-opt it =
+ let size = Option.from 48pt size-opt in
+ FigBox.textbox?:(set-font-size size) it
+
+let big-textbox ?:size-opt it =
+ let size = Option.from 32pt size-opt in
+ FigBox.textbox?:(set-font-size size) it
+
+let mid-textbox ?:size-opt it =
+ let size = Option.from 24pt size-opt in
+ FigBox.textbox?:(set-font-size size) it
+
+let with-frame figbox = figbox
+ |> FigBox.hvmargin 16pt
+ |> FigBox.frame 2pt Color.black
+
+let-block +code-block-php source =
+ '<
+ +code-printer?:(
+ CodePrinter.make-config CodeSyntax.php CodeTheme.iceberg-light
+ |> CodePrinter.set-number-fun CodeDesign.number-fun-null
+ |> CodePrinter.set-basic-font-size 32pt
+ )(source);
+ >
+
+open FigBox
+in
+
+document '<
+ +make-title(|
+ title = {
+ |PHP処理系の
+ |garbage collection を理解する
+ |~メモリはいつ解放されるのか~
+ |};
+ author = {|nsfisis (いまむら)|};
+ date = {|PHPカンファレンス名古屋2025|};
+ |);
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ +frame{自己紹介}<
+ +fig-center(vconcat [
+ gap 30pt;
+ big-textbox{いまむら};
+ ]);
+ +fig-center(vconcat [
+ ex-big-textbox{nsfisis};
+ ]);
+ +fig-center(vconcat [
+ include-image 128pt `assets/me_1200x1200.png`;
+ ]);
+ +fig-center(vconcat [
+ big-textbox{\@ デジタルサーカス株式会社};
+ ]);
+ >
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ +frame{はじめに}<
+ +p{
+ メモリ
+ }
+ +p{
+ コンピュータの一時データ置き場
+ }
+ >
+
+ +frame{はじめに}<
+ +p{
+ メモリの容量は増え続けている
+ }
+ >
+
+ +frame{はじめに}<
+ +p{
+ メモリの容量は増え続けている
+ }
+ +p{}
+ +p{
+ 無限ではない
+ }
+ >
+
+ +frame{はじめに}<
+ +p{
+ 使い果たすと......
+ }
+ >
+
+ +frame{はじめに}<
+ +p{
+ 使い果たすと......
+ }
+ +p{}
+ +listing{
+ * プロセスの強制終了
+ * 極端なパフォーマンスの低下
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ メモリ管理
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ メモリ管理
+ }
+ +p{}
+ +listing{
+ * 必要なメモリを確保する
+ * 不要なメモリを解放する
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ メモリの「確保」(割り当て)
+ }
+ +p{}
+ +p{
+ 必要なメモリのサイズを要求する
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ メモリの「解放」
+ }
+ +p{}
+ +p{
+ 不要になったメモリを再び利用可能にする
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ メモリ管理は難しい
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ メモリ管理は難しい
+ }
+ +p{}
+ +listing{
+ * Memory leak
+ * Double free
+ * Use-after-free
+ * Buffer overflow
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ PHP でメモリ管理を直接おこなう必要はない
+ }
+ >
+
+ +frame{メモリ管理}<
+ +p{
+ PHP でメモリ管理を直接おこなう必要はない
+ }
+ +p{}
+ +p{
+ Garbage Collection
+ }
+ >
+
+ +frame{Garbage Collection}<
+ +p{
+ Garbage Collection (GC)
+ }
+ >
+
+ +frame{Garbage Collection}<
+ +p{
+ Garbage Collection (GC)
+ }
+ +p{}
+ +p{
+ メモリ管理の自動化
+ }
+ +p{
+ 自動でメモリを解放
+ }
+ >
+
+ +frame{PHP の GC 概要}<
+ +p{
+ PHP の GC
+ }
+ >
+
+ +frame{PHP の GC 概要}<
+ +p{
+ PHP の GC
+ }
+ +p{}
+ +p{
+ 参照カウント + マークアンドスイープ
+ }
+ >
+
+ +frame{参照カウント}<
+ +p{
+ 参照カウント
+ }
+ >
+
+ +frame{参照カウント}<
+ +p{
+ 参照カウント
+ }
+ +p{}
+ +p{
+ 参照されている数を数える
+ }
+ +p{
+ ゼロになったら解放する
+ }
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_1.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_2.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_3.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_4.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_5.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_6.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_7.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_8.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_9.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_10.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = ["foo"];
+$b = ["bar"];
+$a[] = $b;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/rc_11.png`);
+ >
+
+ +frame{参照カウント}<
+ +p{
+ 参照カウントの利点
+ }
+ +p{}
+ +listing{
+ * 未使用オブジェクトが即座に解放される
+ * 解放にかかるコストが全体に分散する
+ }
+ >
+
+ +frame{参照カウント}<
+ +p{
+ 参照カウントの欠点
+ }
+ +p{}
+ +listing{
+ * 参照の追加にコストがかかる
+ * マルチスレッド/プロセス環境に向かない
+ * 循環参照を扱えない
+ }
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = new stdClass();
+$b = new stdClass();
+$a->x = $b;
+$b->x = $a;
+
+`#);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = new stdClass();
+$b = new stdClass();
+$a->x = $b;
+$b->x = $a;
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/cycle_1.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = new stdClass();
+$b = new stdClass();
+$a->x = $b;
+$b->x = $a;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/cycle_1.png`);
+ >
+
+ +frame{参照カウント}<
+ +code-block-php(`$a = new stdClass();
+$b = new stdClass();
+$a->x = $b;
+$b->x = $a;
+unset($b);
+unset($a);
+
+`#);
+ +fig-abs-pos((127mm, 40mm))(include-image 127mm `assets/cycle_2.png`);
+ >
+
+ +frame{参照カウント}<
+ +p{
+ 参照カウントでは循環参照を解放できない
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープ (mark & sweep)
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープ (mark & sweep)
+ }
+ +p{}
+ +p{
+ PHP では循環参照の解放のみ担う
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープ (mark & sweep)
+ }
+ +p{}
+ +listing{
+ * 基本的なマークアンドスイープ
+ * PHP でのマークアンドスイープ
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープの流れ
+ }
+ +p{}
+ +listing{
+ * マークフェーズ
+ * スイープフェーズ
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +p{}
+ +listing{
+ * 確実に使われているオブジェクト (ルート) に印を付ける
+ * そこから辿れるオブジェクトに印を付ける
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/ms_1.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/ms_2.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/ms_3.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +p{}
+ +listing{
+ * 全オブジェクトを調べて、印が付いていなければ解放する
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/ms_4.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/ms_5.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ PHP でのマークアンドスイープ
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ PHP でのマークアンドスイープ
+ }
+ +p{}
+ +p{
+ ほとんどのオブジェクトは参照カウントで解放される
+ }
+ +p{
+ 全オブジェクトを走査しなくていい
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ PHP でのマークアンドスイープ
+ }
+ +p{}
+ +p{
+ 循環参照「かもしれない」オブジェクトを登録しておく
+ }
+ +p{
+ そのオブジェクトとそこから辿れるオブジェクトだけ走査する
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ PHP でのマークアンドスイープ
+ }
+ +p{}
+ +p{
+ 循環参照「かもしれない」オブジェクト
+ }
+ +p{}
+ +p{
+ refcount を減らしたときに 0 にならなかったもの
+ }
+ +p{
+ 循環参照は、間接的に自分で自分を指している
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +p{}
+ +listing{
+ * 循環参照かもしれないオブジェクトをルートバッファへ登録する
+ * ルートバッファから辿れる全オブジェクトの refcount を 1減らす
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/msphp_1.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/msphp_2.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +p{}
+ +listing{
+ * すべてのルートバッファから辿れるオブジェクトについて、
+ ** refcount が 0 でないなら1増やす
+ ** refcount が 0 なら解放する
+ * 処理後はルートバッファから取り除く
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/msphp_3.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/msphp_4.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ スイープフェーズ
+ }
+ +fig-abs-pos((60mm, 20mm))(include-image 80mm `assets/msphp_5.png`);
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープが走るタイミング
+ }
+ +p{}
+ +listing{
+ * \code(`gc_collect_cycles()`); を呼んだとき
+ * ルートバッファが一杯になったとき
+ ** デフォルトは 10,000
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープの利点
+ }
+ +p{}
+ +listing{
+ * 循環参照を解放できる
+ * GC が動いていないときのオーバーヘッドがない
+ }
+ >
+
+ +frame{マークアンドスイープ}<
+ +p{
+ マークアンドスイープの欠点
+ }
+ +p{}
+ +listing{
+ * GC に時間がかかる
+ }
+ >
+
+ +frame{振り返り}<
+ +p{
+ PHP の GC
+ }
+ +p{}
+ +p{
+ 参照カウント + マークアンドスイープ
+ }
+ >
+
+ +frame{振り返り}<
+ +p{
+ PHP の GC
+ }
+ +p{}
+ +p{
+ 参照カウント + マークアンドスイープ
+ }
+ +p{}
+ +p{
+ 循環参照以外は参照カウントで、
+ }
+ +p{
+ 循環参照はマークアンドスイープで解放
+ }
+ >
+
+ +frame{振り返り}<
+ +p{
+ PHP の GC
+ }
+ +p{}
+ +p{
+ 参照カウント + マークアンドスイープ
+ }
+ +p{}
+ +p{
+ 多くの (循環参照でない) オブジェクトは未使用になると即座に解放される
+ }
+ +p{
+ 循環参照を形成しているオブジェクトは遅れて解放される
+ }
+ >
+
+ +frame{外部リソースの解放}<
+ +p{
+ \code(`fclose()`); は明示的に呼ぶべきか?
+ }
+ >
+
+ +frame{外部リソースの解放}<
+ +p{
+ \code(`fclose()`); は明示的に呼ぶべきか?
+ }
+ +p{}
+ +p{
+ 明示的に呼ばなくても、GC で解放されたタイミングでクローズされる
+ }
+ >
+
+ +frame{外部リソースの解放}<
+ +p{
+ \code(`fclose()`); は明示的に呼ぶべきか?
+ }
+ +p{}
+ +p{
+ 常に呼ぶべき
+ }
+ >
+
+ +frame{外部リソースの解放}<
+ +p{
+ \code(`fclose()`); は明示的に呼ぶべきか?
+ }
+ +p{}
+ +p{
+ 常に呼ぶべき
+ }
+ +listing{
+ * 呼ばなくても問題ないかを判定するのが困難
+ * 呼ばなくても問題ない状態を維持できるとは限らない
+ }
+ >
+
+ +frame{外部リソースの解放}<
+ +p{
+ \code(`fclose()`); は明示的に呼ぶべきか?
+ }
+ +p{}
+ +p{
+ 常に呼ぶべき
+ }
+ +listing{
+ * 呼ばなくても問題ないかを判定するのが困難
+ * 呼ばなくても問題ない状態を維持できるとは限らない
+ }
+ +p{}
+ +p{
+ 循環参照になっていないか、解放が遅れても問題ないなら呼ばなくてよい
+ }
+ >
+
+ +frame{最後に}<
+ +p{
+ 話せなかったこと
+ }
+ +p{}
+ +listing{
+ * 複数スレッド/プロセス間での共有
+ * リクエスト毎に確保・解放されるメモリとグローバルなメモリ
+ * Copy on Write
+ * 弱参照
+ * \code(`memory_limit`);
+ }
+ >
+
+>