Joe Armstrong の博士論文をサラッと読んだ Closed 作成 2026-10-25 23:30 更新 2026-10-25 23:37 8 comments dak2 2026-10-25 23:30 Making reliable distributed systems in the presence of software errors(KTH, 2003) https://erlang.org/download/armstrong_thesis_2003.pdf Erlang/OTP の設計思想を、作った本人がまとめた論文。 dak2 2026-10-25 23:31 バグは必ず起きる 「バグのないソフトウェアを書く」ではなく、バグは必ず残るのを前提にしている。 問いは「壊れても全体として動き続けるシステムをどう作るか」。 信頼性を正しさではなく、壊れ方の設計として扱っている。 絶対に壊れてはいけない小さな核(error kernel)だけを堅く作り、 それ以外は落ちてもいい前提。 dak2 2026-10-25 23:32 骨子 論文は、並行指向の言語が満たすべき条件をこう並べる。 プロセスがある プロセス同士は強く隔離されている プロセスごとに一意で偽造できない ID がある 状態を共有しない やりとりは届く保証のないメッセージだけ 他のプロセスの死を検知できる dak2 2026-10-25 23:33 Let it crash と supervisor ここでいうプロセスは OS プロセスではなく、BEAM 上の軽量プロセス。 ヒープも GC も個別なので、1 つが落ちても他は巻き込まれない。 エラーは落ちたプロセス自身ではなく、外のプロセスが対処する。 supervisor と子プロセスは link でつながっていて、子プロセスが死ぬと通知が飛ぶ supervisor は trap_exit で、その通知をメッセージとして受け取る 再起動のしかたは戦略で決める(one_for_one / one_for_all / rest_for_one) 短時間に再起動しすぎたら supervisor 自身が死に、親に任せる dak2 2026-10-25 23:34 OS プロセスと Erlang プロセス 「プロセス」が 2 つの意味で出てくるので整理。 OS プロセス(BEAM = Erlang VM) ← 1 個。ps で見えるのはこれ ├─ OS スレッド(スケジューラ)× コア数 ├─ Erlang プロセス A ← 主体 ├─ Erlang プロセス B ← 主体 └─ Erlang プロセス C ... ← 主体(何万個でも) 主体は Erlang プロセス。Erlang プロセスの中にさらに主体がいるわけではなく、1 個 = 1 本の逐次的な流れ supervisor も OS プロセスではなく、ただの Erlang プロセス 同じ OS プロセスの中にいるので、アドレス空間は共有している。でもヒープは別々で、他のプロセスのヒープを指す手段が言語にない メッセージ送信は、受け手の mailbox に値をコピーするだけ。システムコールもソケットもない 隔離を守っているのは OS ではなく言語と VM。なので C で書いた NIF が segfault すると、OS プロセスごと全部死ぬ dak2 2026-10-25 23:35 link と trap_exit supervisor が子プロセスの死をどう知るか。 link は 2 つのプロセスを生死でつなぐ双方向のリンク。片方が死ぬと、もう片方に exit シグナルが飛ぶ 普通のプロセスは、相手が異常終了したときの exit シグナルを受けると一緒に死ぬ(正常終了 normal なら死なない) supervisor は process_flag(trap_exit, true) を立てているので、一緒に死なずに {'EXIT', Pid, Reason} というメッセージとして受け取る 定期的に生死を見に行くのではなく、死んだことが届くだけ 受け取ったあとは、子ごとの設定で再起動するかを決める。 permanent:どんな理由で終わっても再起動 transient:異常終了のときだけ再起動 temporary:再起動しない link はノードもまたげる。別ノードとの接続が切れると、理由が noconnection の通知が届く。ただ、相手が死んだのかネットワークが切れただけなのかは区別できない。 dak2 2026-10-25 23:36 その他おもしろかったところ ホットコードスワップ:モジュールの新旧 2 バージョンが共存し、?MODULE:loop() を通った時点でプロセスが新しいコードに乗り換える。 behaviour:並行処理とエラー処理という難しい部分は OTP が持ち、アプリ側は逐次的なコールバックを書くだけ dak2 2026-10-25 23:37 感想 Erlang/OTP の設計思想知らなかったので興味深い Alan Kay が OOP の核心として言っていた「メッセージング」を一番素直にやっていると思った Erlang は軽くて隔離されたプロセスが設計の基本単位で、プロセス同士は非同期メッセージでやりとり。 事例の章(AXD301)はまだちゃんと読めていないので、そのうち このスクラップはクローズされています
dak2 2026-10-25 23:30 Making reliable distributed systems in the presence of software errors(KTH, 2003) https://erlang.org/download/armstrong_thesis_2003.pdf Erlang/OTP の設計思想を、作った本人がまとめた論文。
dak2 2026-10-25 23:31 バグは必ず起きる 「バグのないソフトウェアを書く」ではなく、バグは必ず残るのを前提にしている。 問いは「壊れても全体として動き続けるシステムをどう作るか」。 信頼性を正しさではなく、壊れ方の設計として扱っている。 絶対に壊れてはいけない小さな核(error kernel)だけを堅く作り、 それ以外は落ちてもいい前提。
dak2 2026-10-25 23:32 骨子 論文は、並行指向の言語が満たすべき条件をこう並べる。 プロセスがある プロセス同士は強く隔離されている プロセスごとに一意で偽造できない ID がある 状態を共有しない やりとりは届く保証のないメッセージだけ 他のプロセスの死を検知できる
dak2 2026-10-25 23:33 Let it crash と supervisor ここでいうプロセスは OS プロセスではなく、BEAM 上の軽量プロセス。 ヒープも GC も個別なので、1 つが落ちても他は巻き込まれない。 エラーは落ちたプロセス自身ではなく、外のプロセスが対処する。 supervisor と子プロセスは link でつながっていて、子プロセスが死ぬと通知が飛ぶ supervisor は trap_exit で、その通知をメッセージとして受け取る 再起動のしかたは戦略で決める(one_for_one / one_for_all / rest_for_one) 短時間に再起動しすぎたら supervisor 自身が死に、親に任せる
dak2 2026-10-25 23:34 OS プロセスと Erlang プロセス 「プロセス」が 2 つの意味で出てくるので整理。 OS プロセス(BEAM = Erlang VM) ← 1 個。ps で見えるのはこれ ├─ OS スレッド(スケジューラ)× コア数 ├─ Erlang プロセス A ← 主体 ├─ Erlang プロセス B ← 主体 └─ Erlang プロセス C ... ← 主体(何万個でも) 主体は Erlang プロセス。Erlang プロセスの中にさらに主体がいるわけではなく、1 個 = 1 本の逐次的な流れ supervisor も OS プロセスではなく、ただの Erlang プロセス 同じ OS プロセスの中にいるので、アドレス空間は共有している。でもヒープは別々で、他のプロセスのヒープを指す手段が言語にない メッセージ送信は、受け手の mailbox に値をコピーするだけ。システムコールもソケットもない 隔離を守っているのは OS ではなく言語と VM。なので C で書いた NIF が segfault すると、OS プロセスごと全部死ぬ
dak2 2026-10-25 23:35 link と trap_exit supervisor が子プロセスの死をどう知るか。 link は 2 つのプロセスを生死でつなぐ双方向のリンク。片方が死ぬと、もう片方に exit シグナルが飛ぶ 普通のプロセスは、相手が異常終了したときの exit シグナルを受けると一緒に死ぬ(正常終了 normal なら死なない) supervisor は process_flag(trap_exit, true) を立てているので、一緒に死なずに {'EXIT', Pid, Reason} というメッセージとして受け取る 定期的に生死を見に行くのではなく、死んだことが届くだけ 受け取ったあとは、子ごとの設定で再起動するかを決める。 permanent:どんな理由で終わっても再起動 transient:異常終了のときだけ再起動 temporary:再起動しない link はノードもまたげる。別ノードとの接続が切れると、理由が noconnection の通知が届く。ただ、相手が死んだのかネットワークが切れただけなのかは区別できない。
dak2 2026-10-25 23:36 その他おもしろかったところ ホットコードスワップ:モジュールの新旧 2 バージョンが共存し、?MODULE:loop() を通った時点でプロセスが新しいコードに乗り換える。 behaviour:並行処理とエラー処理という難しい部分は OTP が持ち、アプリ側は逐次的なコールバックを書くだけ
dak2 2026-10-25 23:37 感想 Erlang/OTP の設計思想知らなかったので興味深い Alan Kay が OOP の核心として言っていた「メッセージング」を一番素直にやっていると思った Erlang は軽くて隔離されたプロセスが設計の基本単位で、プロセス同士は非同期メッセージでやりとり。 事例の章(AXD301)はまだちゃんと読めていないので、そのうち
Making reliable distributed systems in the presence of software errors(KTH, 2003) https://erlang.org/download/armstrong_thesis_2003.pdf
Erlang/OTP の設計思想を、作った本人がまとめた論文。
バグは必ず起きる
「バグのないソフトウェアを書く」ではなく、バグは必ず残るのを前提にしている。 問いは「壊れても全体として動き続けるシステムをどう作るか」。 信頼性を正しさではなく、壊れ方の設計として扱っている。
絶対に壊れてはいけない小さな核(error kernel)だけを堅く作り、 それ以外は落ちてもいい前提。
骨子
論文は、並行指向の言語が満たすべき条件をこう並べる。
Let it crash と supervisor
ここでいうプロセスは OS プロセスではなく、BEAM 上の軽量プロセス。 ヒープも GC も個別なので、1 つが落ちても他は巻き込まれない。
エラーは落ちたプロセス自身ではなく、外のプロセスが対処する。
OS プロセスと Erlang プロセス
「プロセス」が 2 つの意味で出てくるので整理。
link と trap_exit
supervisor が子プロセスの死をどう知るか。
normalなら死なない)process_flag(trap_exit, true)を立てているので、一緒に死なずに{'EXIT', Pid, Reason}というメッセージとして受け取る受け取ったあとは、子ごとの設定で再起動するかを決める。
permanent:どんな理由で終わっても再起動transient:異常終了のときだけ再起動temporary:再起動しないlink はノードもまたげる。別ノードとの接続が切れると、理由が
noconnectionの通知が届く。ただ、相手が死んだのかネットワークが切れただけなのかは区別できない。その他おもしろかったところ
?MODULE:loop()を通った時点でプロセスが新しいコードに乗り換える。感想