rabbit-slide-niku-yapc-hokkaido-2016-eve-naruhodo-erlang-process 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c94ebf71a86f88aed81863cfac708d0860542826
4
+ data.tar.gz: de5a55679ce2ed7c8fc9a89d6a9031a9306437f7
5
+ SHA512:
6
+ metadata.gz: 27def99ad67f1ade53f006a40b45aa4e630927ae81adbcda817530a36c46302c02c5407c2d623adccf72656507dd90ffe25d3b7447dd2b046ac0d88f00f58d64
7
+ data.tar.gz: 8d8e2bf19f3b80225ca0a801a8fdb2cc9ddbdf191bf24a3c014dabddb117653bf37fdd8beb02bc5dff82862f567231fbbc636aa18517860bb988b8f8f4245821
data/.rabbit ADDED
@@ -0,0 +1 @@
1
+ yapc-hokkaido-2016-eve-naruhodo-erlang-process.md
@@ -0,0 +1,24 @@
1
+ # なるほど Erlang プロセス
2
+
3
+ [YAPC::Hokkaido 2016 SAPPORO 前夜祭](http://passmarket.yahoo.co.jp/event/show/detail/0170cmyfxi8j.html) での
4
+ 「なるほどErlangプロセス」発表資料
5
+
6
+ ## 作者向け
7
+
8
+ ### 表示
9
+
10
+ rake
11
+
12
+ ### 公開
13
+
14
+ rake publish
15
+
16
+ ## 閲覧者向け
17
+
18
+ ### インストール
19
+
20
+ gem install rabbit-slide-niku-yapc-hokkaido-2016-eve-naruhodo-erlang-process
21
+
22
+ ### 表示
23
+
24
+ rabbit rabbit-slide-niku-yapc-hokkaido-2016-eve-naruhodo-erlang-process.gem
@@ -0,0 +1,17 @@
1
+ require "rabbit/task/slide"
2
+
3
+ # Edit ./config.yaml to customize meta data
4
+
5
+ spec = nil
6
+ Rabbit::Task::Slide.new do |task|
7
+ spec = task.spec
8
+ # spec.files += Dir.glob("doc/**/*.*")
9
+ # spec.files -= Dir.glob("private/**/*.*")
10
+ # spec.add_runtime_dependency("YOUR THEME")
11
+ end
12
+
13
+ desc "Tag #{spec.version}"
14
+ task :tag do
15
+ sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
16
+ sh("git", "push", "--tags")
17
+ end
@@ -0,0 +1,19 @@
1
+ ---
2
+ id: yapc-hokkaido-2016-eve-naruhodo-erlang-process
3
+ base_name: yapc-hokkaido-2016-eve-naruhodo-erlang-process
4
+ tags: []
5
+ presentation_date:
6
+ version: 1.0.0
7
+ licenses: []
8
+ slideshare_id:
9
+ speaker_deck_id:
10
+ ustream_id:
11
+ vimeo_id:
12
+ youtube_id:
13
+ author:
14
+ markup_language: :markdown
15
+ name: niku
16
+ email: niku@niku.name
17
+ rubygems_user: niku
18
+ slideshare_user:
19
+ speaker_deck_user:
Binary file
@@ -0,0 +1,655 @@
1
+ # なるほど Erlang プロセス
2
+
3
+ author
4
+ niku
5
+ date
6
+ 2016/12/09
7
+
8
+ allotted-time
9
+ : 20m
10
+
11
+ # About me
12
+
13
+ - ヽ(´・肉・`)ノ / @niku_name
14
+ - コンサドーレ札幌が好きです
15
+ - サッポロビームによくいます
16
+
17
+ # なるほど UNIX プロセス
18
+
19
+ ![](naruhounix-cover.jpg){:relative_height='100'}
20
+
21
+ # なるほど UNIX プロセス
22
+
23
+ ```
24
+ 第3章 プロセスにはIDがある
25
+ 第4章 プロセスには親がいる
26
+ 第5章 プロセスにはファイルディスクリプタがある
27
+ 第6章 プロセスにはリソースの制限がある
28
+ 第7章 プロセスには環境がある
29
+ 第8章 プロセスには引数がある
30
+ 第9章 プロセスには名前がある
31
+ 第10章 プロセスには終了コードがある
32
+ 第11章 プロセスは子プロセスを作れる
33
+ 第12章 孤児プロセス
34
+ 第13章 プロセスは優しい
35
+ 第14章 プロセスは待てる
36
+ 第15章 ゾンビプロセス
37
+ 第16章 プロセスはシグナルを受信できる
38
+ 第17章 プロセスは通信できる
39
+ 第18章 デーモンプロセス
40
+ 第19章 端末プロセスを作る
41
+ ```
42
+
43
+ # Erlang
44
+
45
+ - 元々は電話交換機の制御用
46
+ - 耐障害性が高い
47
+ - 並行処理が得意
48
+
49
+ # なるほど Erlang プロセス
50
+
51
+ ```
52
+ Erlang プロセスには ID がある
53
+ Erlang プロセスは子プロセスを作れる
54
+ Erlang プロセスはプロセス毎に値を保持できる
55
+ Erlang プロセスはメッセージを送受信できる
56
+ Erlang プロセスは別々に動ける
57
+ Erlang プロセスは名前を束縛できる
58
+ Erlang プロセスはプロセス数を制限できる
59
+ Erlang プロセスは軽量
60
+ Erlang プロセスは exit シグナルを送る/受けとる
61
+ Erlang プロセスは繋げる
62
+ Erlang プロセスは見ておくことができる
63
+ Erlang プロセスを扱うライブラリ Erlang/OTP
64
+ ```
65
+
66
+ # Erlang プロセスには ID がある
67
+
68
+ ```ruby
69
+ /Users/niku% iex
70
+ iex(1)> self()
71
+ #PID<0.80.0>
72
+ iex(2)>
73
+ ```
74
+
75
+ # Erlang プロセスは子プロセスを作れる
76
+
77
+ ```ruby
78
+ iex(1)> self()
79
+ #PID<0.80.0>
80
+ iex(2)> spawn(fn ->
81
+ ...(2)> IO.inspect self()
82
+ ...(2)> end)
83
+ #PID<0.85.0>
84
+ #PID<0.85.0>
85
+ iex(3)>
86
+ ```
87
+
88
+ # Erlang プロセスはプロセス毎に値を保持できる
89
+
90
+ ```ruby
91
+ iex(1)> Process.put(:a, "foo")
92
+ nil
93
+ iex(2)> Process.get(:a)
94
+ "foo"
95
+ iex(3)> spawn(fn ->
96
+ ...(3)> IO.inspect Process.get(:a)
97
+ ...(3)> end)
98
+ nil
99
+ #PID<0.86.0>
100
+ iex(4)> Process.get(:a)
101
+ "foo"
102
+ iex(5)>
103
+ ```
104
+
105
+ # Erlang プロセスはメッセージを送受信できる
106
+
107
+ プロセスは,メッセージを `send` と `receive` してプロセス間のやりとりを行う.
108
+
109
+ - 送る方 `send` は非同期
110
+ - 受ける方 `receive` は同期(メッセージがくるまでブロックする)
111
+ タイムアウトできる
112
+
113
+ # Erlang プロセスはメッセージを送受信できる
114
+
115
+ ```ruby
116
+ iex(1)> child_pid = spawn(fn ->
117
+ ...(1)> IO.puts "spawned"
118
+ ...(1)> receive do
119
+ ...(1)> x -> IO.puts "#{inspect self()} #{x}"
120
+ ...(1)> end
121
+ ...(1)> IO.puts "received"
122
+ ...(1)> end)
123
+ spawned
124
+ #PID<0.88.0>
125
+ iex(2)> send(child_pid, "hello~")
126
+ #PID<0.88.0> hello~
127
+ received
128
+ "hello~"
129
+ iex(3)>
130
+ ```
131
+
132
+ # Erlang プロセスはメッセージを送受信できる
133
+
134
+ ```ruby
135
+ child_pid = spawn(fn ->
136
+ ...(1)> IO.puts "spawned"
137
+ ...(1)> receive do
138
+ ...(1)> x -> IO.puts "#{inspect self()} #{x}"
139
+ ...(1)> after 10_000 ->
140
+ ...(1)> IO.puts "Timeout"
141
+ ...(1)> end
142
+ ...(1)> IO.puts "received"
143
+ ...(1)> end)
144
+ spawned
145
+ #PID<0.91.0>
146
+ iex(2)>
147
+ nil
148
+ iex(3)> # 10秒待つ
149
+ nil
150
+ iex(4)> Timeout
151
+ iex(4)> received
152
+ iex(4)>
153
+ ```
154
+
155
+ # Erlang プロセスはメッセージを送受信できる
156
+
157
+ 送る方は send で勝手におくりつけてくる
158
+ 受ける方は receive を明示的に呼ばないと,メッセージを受ける体制に入らない
159
+
160
+ `x = x + 1` をマルチスレッドで動かすとおかしくなるような問題が起きない
161
+
162
+ # Erlang プロセスは別々に動ける
163
+
164
+ ```ruby
165
+ # fib.exs
166
+ defmodule Fib do
167
+ def calc(n) when n == 0, do: 0
168
+ def calc(n) when n == 1, do: 1
169
+ def calc(n) when 2 <= n do
170
+ calc(n - 1) + calc(n - 2)
171
+ end
172
+
173
+ def calc_three_processes_in_parallel(n) do
174
+ me = self()
175
+ # 3並列に計算し,完了したら答えを送ってもらう
176
+ spawn(fn -> send(me, calc(n)) end)
177
+ spawn(fn -> send(me, calc(n)) end)
178
+ spawn(fn -> send(me, calc(n)) end)
179
+ do_receive([])
180
+ end
181
+
182
+ defp do_receive(result) when length(result) == 3 do
183
+ result
184
+ end
185
+ defp do_receive(result) when length(result) < 3 do
186
+ receive do
187
+ x ->
188
+ do_receive([x | result])
189
+ end
190
+ end
191
+ end
192
+ ```
193
+
194
+ # Erlang プロセスは別々に動ける
195
+
196
+ ```elixir
197
+ iex(1)> import_file("fib.exs")
198
+ {:module, Fib,
199
+ <<70, 79, 82, 49, 0, 0, 9, 152, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 219,
200
+ 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
201
+ 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>, {:do_receive, 1}}
202
+ iex(2)> {single_execution_time, answer} =
203
+ :timer.tc(Fib, :calc, [40])
204
+ {7219356, 102334155}
205
+ iex(3)> {multi_execution_time, answer} =
206
+ :timer.tc(Fib, :calc_three_processes_in_parallel, [40])
207
+ {10781720, [102334155, 102334155, 102334155]}
208
+ iex(4)> multi_execution_time / single_execution_time
209
+ 1.4934462298299183
210
+ iex(5)>
211
+ ```
212
+
213
+ # Erlang プロセスは名前を束縛できる
214
+
215
+ ```ruby
216
+ iex(1)> child_pid = spawn(fn ->
217
+ ...(1)> receive do
218
+ ...(1)> x -> IO.puts "#{inspect self()}: #{x}"
219
+ ...(1)> end
220
+ ...(1)> end)
221
+ #PID<0.109.0>
222
+ iex(2)> Process.register(child_pid, :echo)
223
+ true
224
+ iex(3)> send(:echo, "hi")
225
+ #PID<0.109.0>: hi
226
+ "hi"
227
+ iex(4)>
228
+ ```
229
+
230
+ # Erlang プロセスはプロセス数を制限できる
231
+
232
+ ```ruby
233
+ iex(1)> :erlang.system_info(:process_limit)
234
+ 262144
235
+ iex(2)>
236
+ ```
237
+
238
+ # Erlang プロセスはプロセス数を制限できる
239
+
240
+ ```ruby
241
+ /Users/niku% ELIXIR_ERL_OPTIONS="+P 1024" iex
242
+ iex(1)> :erlang.system_info(:process_limit)
243
+ 1024
244
+ iex(2)> Enum.map(0..1024, fn n ->
245
+ ...(2)> IO.puts Enum.count(Process.list())
246
+ ...(2)> spawn(fn ->
247
+ ...(2)> receive do
248
+ ...(2)> x -> IO.inspect x
249
+ ...(2)> end
250
+ ...(2)> end)
251
+ ...(2)> end)
252
+ 43
253
+ 44
254
+ (...snip...)
255
+ 1022
256
+ 1023
257
+ 1024
258
+ ** (SystemLimitError) a system limit has been reached
259
+
260
+ 23:12:15.338 [error] Too many processes
261
+ ```
262
+
263
+ # Erlang プロセスは軽量
264
+
265
+ ```ruby
266
+ iex(1)> f = fn ->
267
+ ...(1)> receive do
268
+ ...(1)> after :infinity -> :ok
269
+ ...(1)> end
270
+ ...(1)> end
271
+ #Function<20.52032458/0 in :erl_eval.expr/5>
272
+ iex(2)> {_, total_bytes} = Process.info(spawn(f), :memory)
273
+ {:memory, 2720}
274
+ iex(3)> wordsize = :erlang.system_info(:wordsize)
275
+ 8
276
+ iex(4)> total_bytes / wordsize
277
+ 340.0
278
+ iex(5)> {_, heap_size} = Process.info(spawn(f), :heap_size)
279
+ {:heap_size, 233}
280
+ iex(6)>
281
+ ```
282
+
283
+ # Erlang プロセスは軽量
284
+
285
+ - 1プロセス作るのにヒープ領域込みで最小 309 words( *2472バイト* )
286
+ - この環境では Hipe という拡張が有効になっているため 340 words になっている
287
+
288
+ # Erlang プロセスは軽量
289
+
290
+ 100万プロセス動かす
291
+
292
+ # Erlang プロセスは軽量
293
+
294
+ ```ruby
295
+ # chain.exs
296
+ defmodule Chain do
297
+ def create_processes(n) do
298
+ # n個目の(最後の)プロセスは親プロセスにメッセージを送る
299
+ last_pid = Enum.reduce(1..n, self(), fn (_, send_to) ->
300
+ spawn(fn ->
301
+ # メッセージを受けたら1足して次のメッセージに送る
302
+ receive do
303
+ x -> send(send_to, x + 1)
304
+ end
305
+ end)
306
+ end)
307
+ IO.puts "count: #{Enum.count(Process.list())}, memory: :#{:erlang.memory(:total)}"
308
+ send(last_pid, 0) # n個の子プロセスの最初の1個を動かす
309
+
310
+ receive do
311
+ final_answer -> "Result is #{final_answer}"
312
+ end
313
+ end
314
+
315
+ def run(n) do
316
+ {execution_micro_secs, final_answer} =
317
+ :timer.tc(Chain, :create_processes, [n])
318
+ seconds = execution_micro_secs / (1000 * 1000)
319
+ IO.puts "#{seconds} seconds, #{final_answer}"
320
+ end
321
+ end
322
+ ```
323
+
324
+ # Erlang プロセスは軽量
325
+
326
+ ```bash
327
+ /Users/niku% system_profiler SPHardwareDataType
328
+ Hardware:
329
+
330
+ Hardware Overview:
331
+
332
+ Model Name: MacBook Pro
333
+ Model Identifier: MacBookPro12,1
334
+ Processor Name: Intel Core i5
335
+ Processor Speed: 2.7 GHz
336
+ Number of Processors: 1
337
+ Total Number of Cores: 2
338
+ L2 Cache (per Core): 256 KB
339
+ L3 Cache: 3 MB
340
+ Memory: 16 GB
341
+ (...snip...)
342
+
343
+ /Users/niku% ELIXIR_ERL_OPTIONS="+P 10000000" elixir -r chain.exs -e "Chain.run(1_000_000)"
344
+ count: 1000037, memory: :2970141432
345
+ 8.74099 seconds, Result is 1000000
346
+ ```
347
+
348
+ # Erlang プロセスは軽量
349
+
350
+ 軽量2つの利点
351
+
352
+ - かかった時間8.75秒 -> プロセス作成の速さ
353
+ - 使用メモリ3GB弱 -> 省メモリ
354
+
355
+ *カジュアルに殺したり作ったりしやすい*
356
+
357
+ # Erlang プロセスは exit シグナルを送る/受けとる
358
+
359
+ 2種類の exit シグナル
360
+
361
+ 1. `exit(:normal)` :: 受けとった方は何もしない
362
+ 2. `exit(任意の値)` :: 受けとった方は死ぬ
363
+
364
+ # Erlang プロセスは exit シグナルを送る/受けとる
365
+
366
+ ```ruby
367
+ iex(1)> other_pid = spawn(fn ->
368
+ ...(1)> receive do
369
+ ...(1)> x -> IO.puts x
370
+ ...(1)> end
371
+ ...(1)> end)
372
+ #PID<0.88.0>
373
+ iex(2)> Process.alive?(other_pid)
374
+ true
375
+ iex(3)> Process.exit(other_pid, :normal)
376
+ true
377
+ iex(4)> Process.alive?(other_pid)
378
+ true
379
+ iex(5)> Process.exit(other_pid, :omg)
380
+ true
381
+ iex(6)> Process.alive?(other_pid)
382
+ false
383
+ iex(7)>
384
+ ```
385
+
386
+ # Erlang プロセスは exit シグナルを送る/受けとる
387
+
388
+ exit シグナルも特別なメッセージにすぎない
389
+
390
+ # Erlang プロセスは exit シグナルを送る/受けとる
391
+
392
+ ```ruby
393
+ iex(1)> other_pid = spawn(fn ->
394
+ ...(1)> Process.flag(:trap_exit, true)
395
+ ...(1)> receive do
396
+ ...(1)> x -> IO.inspect x
397
+ ...(1)> end
398
+ ...(1)> end)
399
+ #PID<0.88.0>
400
+ iex(2)>
401
+ nil
402
+ iex(3)> Process.exit(other_pid, :omg)
403
+ {:EXIT, #PID<0.81.0>, :omg}
404
+ true
405
+ iex(4)>
406
+ ```
407
+
408
+ # Erlang プロセスはシグナルを送る/受けとる
409
+
410
+ exit シグナルを受けとって死ぬことに意味はあるのか?
411
+
412
+ 次に挙げる特徴と組合せると便利
413
+
414
+ # Erlang プロセスは繋げる
415
+
416
+ - プロセスを繋げる(linkする)ことができる
417
+ - *繋がっていないプロセス* で何があっても *影響を受けない*
418
+ - *繋がっているプロセス* は *exitシグナルを受けとる*
419
+
420
+ # Erlang プロセスは繋げる
421
+
422
+ ```ruby
423
+ iex(1)> spawn(fn ->
424
+ ...(1)> Process.flag(:trap_exit, true)
425
+ ...(1)>
426
+ ...(1)> spawn(fn ->
427
+ ...(1)> exit(:omg)
428
+ ...(1)> end)
429
+ ...(1)>
430
+ ...(1)> receive do
431
+ ...(1)> message ->
432
+ ...(1)> IO.puts "An exit signal received: #{inspect message}"
433
+ ...(1)> after 1000 ->
434
+ ...(1)> IO.puts "timeout"
435
+ ...(1)> end
436
+ ...(1)> end)
437
+ #PID<0.96.0>
438
+ iex(2)>
439
+ nil
440
+ iex(3)> timeout
441
+ iex(3)>
442
+ ```
443
+
444
+ # Erlang プロセスは繋げる
445
+
446
+ ```ruby
447
+ iex(1)> spawn(fn ->
448
+ ...(1)> Process.flag(:trap_exit, true)
449
+ ...(1)>
450
+ ...(1)> spawn_link(fn ->
451
+ ...(1)> exit(:omg)
452
+ ...(1)> end)
453
+ ...(1)>
454
+ ...(1)> receive do
455
+ ...(1)> message ->
456
+ ...(1)> IO.puts "An exit signal received: #{inspect message}"
457
+ ...(1)> after 1000 ->
458
+ ...(1)> IO.puts "timeout"
459
+ ...(1)> end
460
+ ...(1)> end)
461
+ #PID<0.96.0>
462
+ An exit signal received: {:EXIT, #PID<0.97.0>, :omg}
463
+ iex(2)>
464
+ nil
465
+ iex(3)>
466
+ ```
467
+
468
+ # Erlang プロセスは繋げる
469
+
470
+ `exit` シグナルはハンドリングしないエラーがプロセスに到達した場合にも発生する
471
+
472
+ # Erlang プロセスは繋げる
473
+
474
+ ```ruby
475
+ iex(1)> spawn(fn ->
476
+ ...(1)> Process.flag(:trap_exit, true)
477
+ ...(1)>
478
+ ...(1)> spawn_link(fn ->
479
+ ...(1)> 1 / 0
480
+ ...(1)> end)
481
+ ...(1)>
482
+ ...(1)> receive do
483
+ ...(1)> message ->
484
+ ...(1)> IO.puts "An exit signal received: #{inspect message}"
485
+ ...(1)> end
486
+ ...(1)> end)
487
+ #PID<0.110.0>
488
+ iex(2)>
489
+ 23:45:15.070 [error] Process #PID<0.111.0> raised an exception
490
+ ** (ArithmeticError) bad argument in arithmetic expression
491
+ :erlang./(1, 0)
492
+ An exit signal received: {:EXIT, #PID<0.111.0>, {:badarith, [{:erlang, :/, [1, 0], []}]}}
493
+ iex(2)>
494
+ ```
495
+
496
+ # Erlang プロセスは繋げる
497
+
498
+ [再掲] exit シグナルを受けとって死ぬことに意味はあるのか?
499
+
500
+ # Erlang プロセスは繋げる
501
+
502
+ > もしエラーのあるプロセスがクラッシュしたけれど、それに依存しているプロセスが動き続けているとしたら、それら依存プロセスすべては依存先がなくなったことに対処しなければならなくなります。
503
+
504
+ すごいErlangゆかいに学ぼう!第 12 章 - エラーとプロセス
505
+
506
+ # Erlang プロセスは繋げる
507
+
508
+ - 意味のあるグループで複数のプロセスを繋げる :: *プロセス管理対象数の抑制*
509
+ - 1つのプロセスが死んだらグループ全てのプロセスが死ぬ :: *グループの中途半端な状態の抑制*
510
+ - 死んだことがすぐ検知できる :: *すぐ新しいプロセスを作ることができる*
511
+
512
+ # Erlang プロセスは繋げる
513
+
514
+ - 静的型付き言語はランタイムエラーを起こさないことを目指すことで(100%の)安定動作を目指せる
515
+ - ErlangVM はエラーになったときに,検知/再開を素早く行うことを目指すことで(99.9...%の)安定動作を目指せる
516
+
517
+ *ソースなし(私見)*
518
+
519
+ # Erlang プロセスは見ておくことができる
520
+
521
+ - プロセスを見ておく(monitor)できる
522
+ - 見るプロセス,見られるプロセスという立場が存在する
523
+ - 2 つのプロセス間で複数のモニターが持てる(スタックでき,それぞれに識別できる)
524
+
525
+ # Erlang プロセスは見ておくことができる
526
+
527
+ - 見る方が死んでも,見られる方には関係ない
528
+ - モニターを複数作れる
529
+
530
+ ライブラリのような,相互に強固に結びついていないプロセスが,他のプロセスを監視するのに向いている
531
+
532
+ # Erlang プロセスは見ておくことができる
533
+
534
+ ```ruby
535
+ iex(1)> spawn(fn ->
536
+ ...(1)> spawn_monitor(fn ->
537
+ ...(1)> exit(:omg)
538
+ ...(1)> end)
539
+ ...(1)>
540
+ ...(1)> receive do
541
+ ...(1)> message ->
542
+ ...(1)> IO.puts "An exit signal received: #{inspect message}"
543
+ ...(1)> end
544
+ ...(1)> end)
545
+ #PID<0.92.0>
546
+ An exit signal received: {:DOWN, #Reference<0.0.4.260>, :process, #PID<0.93.0>, :omg}
547
+ iex(2)>
548
+ nil
549
+ iex(3)>
550
+ ```
551
+
552
+ # Erlang プロセスを扱うライブラリ Erlang/OTP
553
+
554
+ - 本体に同梱されている
555
+ - プロセス間のインタラクションをいい感じに
556
+
557
+ # Erlang プロセスを扱うライブラリ Erlang/OTP
558
+
559
+ ```ruby
560
+ # stack.exs
561
+ defmodule Stack do
562
+ use GenServer # OTPに含まれるライブラリ
563
+
564
+ def start_link(state, opts \\ []) do
565
+ GenServer.start_link(__MODULE__, state, opts)
566
+ end
567
+
568
+ # 初期化
569
+ def init(state) do
570
+ {:ok, state}
571
+ end
572
+
573
+ # 同期呼び出し
574
+ def handle_call(:pop, _from, [h | t]) do
575
+ {:reply, h, t}
576
+ end
577
+
578
+ # 非同期呼び出し
579
+ def handle_cast({:push, item}, state) do
580
+ {:noreply, [item | state]}
581
+ end
582
+ end
583
+ ```
584
+
585
+ # Erlang プロセスを扱うライブラリ Erlang/OTP
586
+
587
+ ```elixir
588
+ iex(1)> import_file("stack.exs")
589
+ {:module, Stack,
590
+ <<70, 79, 82, 49, 0, 0, 12, 104, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 2, 144,
591
+ 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
592
+ 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>, {:handle_cast, 2}}
593
+ iex(2)> import Supervisor.Spec
594
+ Supervisor.Spec
595
+ iex(3)> children = [
596
+ ...(3)> worker(Stack, [[:hello], [name: MyStack]])
597
+ ...(3)> ]
598
+ [{Stack, {Stack, :start_link, [[:hello], [name: MyStack]]}, :permanent, 5000,
599
+ :worker, [Stack]}]
600
+ iex(4)> {:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
601
+ {:ok, #PID<0.91.0>}
602
+ ```
603
+
604
+ # Erlang プロセスを扱うライブラリ Erlang/OTP
605
+
606
+ ```ruby
607
+ iex(5)> GenServer.call(MyStack, :pop)
608
+ :hello
609
+ iex(6)> GenServer.cast(MyStack, {:push, :world})
610
+ :ok
611
+ iex(7)> GenServer.call(MyStack, :pop)
612
+ :world
613
+ iex(8)> GenServer.call(MyStack, :pop)
614
+ (...snip...)
615
+ 17:08:37.217 [error] GenServer MyStack terminating
616
+ ** (FunctionClauseError) no function clause matching in Stack.handle_call/3
617
+ iex:15: Stack.handle_call(:pop, {#PID<0.80.0>, #Reference<0.0.4.299>}, [])
618
+ (stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
619
+ (stdlib) gen_server.erl:647: :gen_server.handle_msg/5
620
+ (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
621
+ Last message: :pop
622
+ State: []
623
+ (elixir) lib/gen_server.ex:737: GenServer.call/3
624
+ iex(8)> GenServer.call(MyStack, :pop)
625
+ :hello
626
+ iex(9)>
627
+ ```
628
+
629
+ # 今日話したこと
630
+
631
+ - ErlangVM のプロセス軽量
632
+ - ErlangVM のプロセス間のやりとり,エラー処理
633
+ - メッセージパッシング
634
+ - リンク
635
+ - モニター
636
+ - 使いやすくしたライブラリ OTP
637
+
638
+ # まとめ
639
+
640
+ - プロセス同士のインタラクションで耐障害性を担保
641
+ - 土台(プロセス)から上については意識する機会が多い
642
+ - 土台(プロセス)とか,土台(プロセス)同士のインタラクションとか意識して知ると便利かもよ
643
+
644
+ # まとめ
645
+
646
+ だいたい毎週木曜日19:00から ErlangVM やそうでないことについてわいわいやる *オンライン参加もできる* サッポロビーム
647
+
648
+ # 今日話したこと
649
+
650
+ - ErlangVM のプロセス軽量
651
+ - ErlangVM のプロセス間のやりとり,エラー処理
652
+ - メッセージパッシング
653
+ - リンク
654
+ - モニター
655
+ - 使いやすくしたライブラリ OTP
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbit-slide-niku-yapc-hokkaido-2016-eve-naruhodo-erlang-process
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - niku
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rabbit
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.2
27
+ description: |-
28
+ [YAPC::Hokkaido 2016 SAPPORO 前夜祭](http://passmarket.yahoo.co.jp/event/show/detail/0170cmyfxi8j.html) での
29
+ 「なるほどErlangプロセス」発表資料
30
+ email:
31
+ - niku@niku.name
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - ".rabbit"
37
+ - README.md
38
+ - Rakefile
39
+ - config.yaml
40
+ - naruhounix-cover.jpg
41
+ - pdf/yapc-hokkaido-2016-eve-naruhodo-erlang-process-yapc-hokkaido-2016-eve-naruhodo-erlang-process.pdf
42
+ - yapc-hokkaido-2016-eve-naruhodo-erlang-process.md
43
+ homepage: http://slide.rabbit-shocker.org/authors/niku/yapc-hokkaido-2016-eve-naruhodo-erlang-process/
44
+ licenses: []
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 2.5.1
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: なるほど Erlang プロセス
66
+ test_files: []