rabbit-slide-niku-erlangvm-for-pythonista 2015.09.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 04fc57f2da32392e79b88baaf3ed4ac1ac3d1278
4
+ data.tar.gz: 2ccb4017043cf55bd301952291bd808148b94984
5
+ SHA512:
6
+ metadata.gz: 097fccf3cf57c999cf101efb280e90e397fc9c06fe25d42704408beea196fc4b0b0845cbedb0cd8776bb9ac9ded4317db62ecf324fe1e58e8c6733dac5e72409
7
+ data.tar.gz: dd3922687cc6f94d68996f5167eb6dd5bb077a2d6181b139660006f9f22f1b4689378fb7761bc9d33e00f1ba6a4fa24e9597638d6baf642329b9865771e3691e
data/.rabbit ADDED
@@ -0,0 +1 @@
1
+ erlangvm-for-pythonista.md
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # 蛇とビーム
2
+
3
+ ErlangVM for Pythonista
4
+
5
+ ## 作者向け
6
+
7
+ ### 表示
8
+
9
+ rake
10
+
11
+ ### 公開
12
+
13
+ rake publish
14
+
15
+ ## 閲覧者向け
16
+
17
+ ### インストール
18
+
19
+ gem install rabbit-slide-niku-erlangvm-for-pythonista
20
+
21
+ ### 表示
22
+
23
+ rabbit rabbit-slide-niku-erlangvm-for-pythonista.gem
data/Rakefile ADDED
@@ -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
data/config.yaml ADDED
@@ -0,0 +1,20 @@
1
+ ---
2
+ id: erlangvm-for-pythonista
3
+ base_name: erlangvm-for-pythonista
4
+ tags:
5
+ - elixir
6
+ presentation_date: 2015/09/12
7
+ version: 2015.09.12
8
+ licenses: []
9
+ slideshare_id:
10
+ speaker_deck_id:
11
+ ustream_id:
12
+ vimeo_id:
13
+ youtube_id:
14
+ author:
15
+ markup_language: :markdown
16
+ name: niku
17
+ email: niku@niku.name
18
+ rubygems_user: niku
19
+ slideshare_user:
20
+ speaker_deck_user: niku
@@ -0,0 +1,491 @@
1
+ # 蛇とビーム
2
+
3
+ author
4
+ niku
5
+ date
6
+ 2015/09/12
7
+ allotted-time
8
+ 5m
9
+
10
+ # ヽ(´・肉・`)ノ
11
+
12
+ - にくです
13
+ - 農業とITをつなぐベンチャーで働いています
14
+ - コンサドーレ札幌が好きです
15
+
16
+ # 発表の目的
17
+
18
+ 必要なときに ErlangVM を思い出して
19
+ 選択肢として含められるようにすること
20
+
21
+ # サッポロビームの方から
22
+
23
+ http://sapporo-beam.github.io/
24
+
25
+ ErlangVMに載っている言語に関する話題やそうでない話題でわいわいやる集まりです.
26
+ だいたい毎週木曜日にやっています.
27
+
28
+ このまえ 80 回目でした
29
+
30
+ # ビーム(Beam)
31
+
32
+ http://www.ymotongpoo.com/works/lyse-ja/ja/04_modules.html#id3
33
+
34
+ `.beam` はBogdan/BjörnさんのErlang抽象マシン(Bogdan/Björn's Erlang Abstract Machine)を表しています。この名前はVM自身の名前です。
35
+
36
+ # ErlangVM
37
+
38
+ そもそもは Erlang という言語のために作られ,育てられた VM
39
+
40
+ # Erlang
41
+
42
+ そもそもは ERICSSON という会社で作られた言語
43
+
44
+ # ERICSSON
45
+
46
+ スウェーデンにある通信機器メーカー
47
+
48
+ # 通信機器ソフトに求められる
49
+
50
+ - 処理を並行してたくさん行う
51
+ - 障害をのりきって動く
52
+ - バージョンアップ中にも動く
53
+ - それなりに速く動作する
54
+
55
+ # ErlangVM もまた
56
+
57
+ - 処理を並行してたくさん行う
58
+ - 障害をのりきって動く
59
+ - バージョンアップ中にも動く
60
+ - それなりに速く動作する
61
+
62
+ # 日本だと
63
+
64
+ http://www.slideshare.net/takahiro_yachi/ss-44828680
65
+
66
+ ドワンゴさんのニコニコ生放送は Erlang で運用されているみたい
67
+
68
+ # (`・肉・)<よさそう
69
+
70
+ フフ,そうでしょうとも.
71
+
72
+ # (´・肉・)<知らないなあ
73
+
74
+ アッ……ハイ
75
+
76
+ すごくよく話題に登るわけではない
77
+
78
+ # 出自が異なる
79
+
80
+ http://archive.oreilly.com/pub/a/oreilly//news/languageposter_0504.html
81
+
82
+ - Python は C 由来(たぶん?)
83
+ - Erlang は Prolog 由来
84
+
85
+ C で見慣れた構文とは少し違う
86
+
87
+ # Erlang コードの例
88
+
89
+ 運転免許の例
90
+
91
+ ```erlang
92
+ -module(license).
93
+ -export([right_age/1]).
94
+
95
+ right_age(X) when X >= 16, X =< 104 ->
96
+ true;
97
+ right_age(_) ->
98
+ false.
99
+ ```
100
+
101
+ - 慣れると特に困らない(みたい
102
+
103
+ # Elixir コードの例
104
+
105
+ ```ruby
106
+ defmodule License do
107
+ def right_age(x) when x >= 16 and x <= 104, do: true
108
+ def right_age(_), do: false
109
+ end
110
+ ```
111
+
112
+ - ErlangVM で使える言語 Elixir
113
+ - 速度ペナルティはない
114
+ - 多少みたことある感じ
115
+
116
+ # 今回は Elixir で説明します
117
+
118
+ - 僕が慣れているため
119
+ - 当然 Erlang でも同じことができます
120
+
121
+ # 処理を並行してたくさん行う
122
+
123
+ 重くてどのくらいかかるかわからない処理を 6 個行う.
124
+ 結果がわかった順に 2 つ 1 組のペアにして表示する.
125
+ ただし 5 秒待って何も結果が出なければタイムアウトする.
126
+
127
+ 好きな言語で実装してみよう
128
+
129
+ # 処理を並行してたくさん行う
130
+
131
+ ```ruby
132
+ defmodule Producer do
133
+ def produce(dest_pid) do
134
+ Stream.repeatedly(&:random.uniform/0) # ランダムな値
135
+ |> Stream.with_index # n 番目
136
+ |> Stream.each(fn {random, index} -> # {ランダムな値, n 番目}
137
+ spawn fn -> # 別プロセスを作る
138
+ sleeptime = trunc(random * 2 * 1000)
139
+ IO.puts "Producer #{index} 計算時間: #{sleeptime}ms"
140
+ :timer.sleep(sleeptime) # 0-2 秒待って(重い処理のつもり)
141
+ IO.puts "Producer #{index} 送りまーす"
142
+ send(dest_pid, index) # dest_pid に結果を送る
143
+ end
144
+ end)
145
+ end
146
+ end
147
+ ```
148
+
149
+ # 処理を並行してたくさん行う
150
+
151
+ ```ruby
152
+ defmodule Consumer do
153
+ def consume(list) do
154
+ IO.puts "Consumer まちまーす(list の長さ #{length list})"
155
+ receive do
156
+ x -> # x を受けとったら
157
+ IO.puts "Consumer #{x} 受けましたー"
158
+ if length(list) == 1 do
159
+ IO.puts "Consumer ペアは #{hd(list)} と #{x} です"
160
+ consume([])
161
+ else
162
+ consume([x])
163
+ end
164
+ after
165
+ 5000 -> # 5 秒待ったら打ち切る
166
+ IO.puts "Consumer 時間切れ"
167
+ end
168
+ end
169
+ end
170
+ ```
171
+
172
+ # 処理を並行してたくさん行う
173
+
174
+ https://gist.github.com/niku/5796caa4aec4f9edd438
175
+
176
+ 実行する
177
+
178
+ ```ruby
179
+ :random.seed(:os.timestamp) # ランダムな値を生成するための処理
180
+ # (おまじない)
181
+ Enum.take(Producer.produce(self()), 6) # 自分のプロセス self() に 6 個作って送る
182
+ Consumer.consume([]) # メッセージが送られてくるのを待つ
183
+ ```
184
+
185
+ # 処理を並行してたくさん行う
186
+
187
+ ```
188
+ Consumer まちまーす(list の長さ 0)
189
+ Producer 0 計算時間: 1129ms
190
+ Producer 1 計算時間: 776ms
191
+ Producer 2 計算時間: 174ms
192
+ Producer 3 計算時間: 909ms
193
+ Producer 4 計算時間: 1474ms
194
+ Producer 5 計算時間: 1328ms
195
+ Producer 2 送りまーす
196
+ Consumer 2 受けましたー
197
+ Consumer まちまーす(list の長さ 1)
198
+ Producer 1 送りまーす
199
+ Consumer 1 受けましたー
200
+ Consumer ペアは 2 と 1 です
201
+ Consumer まちまーす(list の長さ 0)
202
+ Producer 3 送りまーす
203
+ Consumer 3 受けましたー
204
+ Consumer まちまーす(list の長さ 1)
205
+ Producer 0 送りまーす
206
+ Consumer 0 受けましたー
207
+ Consumer ペアは 3 と 0 です
208
+ Consumer まちまーす(list の長さ 0)
209
+ Producer 5 送りまーす
210
+ Consumer 5 受けましたー
211
+ Consumer まちまーす(list の長さ 1)
212
+ Producer 4 送りまーす
213
+ Consumer 4 受けましたー
214
+ Consumer ペアは 5 と 4 です
215
+ Consumer まちまーす(list の長さ 0)
216
+ Consumer 時間切れ
217
+ ```
218
+
219
+ # 障害をのりきって動く
220
+
221
+ 「最初は 0 で初期化,値がきたら今までの値と足し合わせる.
222
+ エラーになったら合計を表示する.
223
+ その後また初期化から処理を再開する」
224
+ というモジュールを作る.
225
+
226
+ 好きな言語で実装してみよう
227
+
228
+ # 障害をのりきって動く
229
+
230
+ http://www.ymotongpoo.com/works/lyse-ja/ja/01_introduction.html#erlang
231
+
232
+ Erlangの一般的なポリシーをお教えします:「クラッシュするならさせておけ」です。(略)
233
+ 下にネットが敷いてある綱渡りのようなものです。
234
+
235
+ # 障害をのりきって動く
236
+
237
+ **Let it crash**
238
+ (クラッシュするならさせておけ)
239
+
240
+ (`・肉・)< **信じて作る**
241
+
242
+ # 障害をのりきって動く
243
+
244
+ ```ruby
245
+ defmodule Calculator do
246
+ use GenServer
247
+ # Client
248
+ def start_link(number), do: GenServer.start_link(__MODULE__, number, name: __MODULE__)
249
+ def plus(x), do: GenServer.cast(__MODULE__, {:plus, x})
250
+
251
+ # Server
252
+ def init(number) do
253
+ IO.puts "#{number} から始めまーす"
254
+ {:ok, number}
255
+ end
256
+
257
+ def handle_cast({:plus, x}, state) do
258
+ IO.puts "#{state} に #{x} を足しまーす"
259
+ {:noreply, state + x}
260
+ end
261
+
262
+ def terminate(_reason, state) do
263
+ IO.puts "#{state} で終わりまーす"
264
+ :ok
265
+ end
266
+ end
267
+ ```
268
+
269
+ # 障害をのりきって動く
270
+
271
+ ```
272
+ $ iex -r let-it-crash.exs
273
+ iex(1)> Calculator.start_link(0)
274
+ 0 から始めまーす
275
+ {:ok, #PID<0.68.0>}
276
+ iex(2)> Calculator.plus(1)
277
+ 0 に 1 を足しまーす
278
+ :ok
279
+ iex(3)> Calculator.plus(3)
280
+ 1 に 3 を足しまーす
281
+ :ok
282
+ iex(4)> Calculator.plus("bom!")
283
+ 4 に bom! を足しまーす
284
+ :ok
285
+ 4 で終わりまーす
286
+ (略)
287
+ iex(1)> Calculator.plus(2)
288
+ ** (ArgumentError) argument error
289
+ :erlang.send(Calculator, {:"$gen_cast", {:plus, 2}})
290
+ (elixir) lib/gen_server.ex:614: GenServer.do_send/2
291
+ ```
292
+
293
+ # 障害をのりきって動く
294
+
295
+ (´・肉・)< **障害のりきれなかた**
296
+
297
+ # 障害をのりきって動く
298
+
299
+ 「最初は 0 で初期化,値がきたら今までの値と足し合わせる.
300
+ エラーになったら合計を表示する.
301
+ ------- ここまでできた --------
302
+ その後また初期化から処理を再開する」
303
+ というモジュールを作る.
304
+
305
+ # 障害をのりきって動く
306
+
307
+ http://www.ymotongpoo.com/works/lyse-ja/ja/01_introduction.html#erlang
308
+
309
+ Erlangの一般的なポリシーをお教えします:「クラッシュするならさせておけ」です。(略)
310
+ 下にネットが敷いてある綱渡りのようなものです。
311
+
312
+ (´・肉・)<**ネット敷いてなかた**
313
+
314
+ # 障害をのりきって動く
315
+
316
+ ErlangVM においてのネット
317
+ それは **Supervisor** (監視者)
318
+
319
+ Worker が綱から落ちたら再挑戦させてくれる
320
+
321
+ # 障害をのりきって動く
322
+
323
+ ```ruby
324
+ defmodule Calculator.Supervisor do
325
+ use Supervisor
326
+
327
+ def start_link, do: Supervisor.start_link(__MODULE__, [])
328
+
329
+ def init(_arg) do
330
+ # 監視する対象を指定して
331
+ children = [
332
+ worker(Calculator, [0])
333
+ ]
334
+
335
+ # 監視する
336
+ supervise(children, strategy: :one_for_one)
337
+ end
338
+ end
339
+ ```
340
+
341
+ # 障害をのりきって動く
342
+
343
+ ```
344
+ $ iex -r let-it-crash.exs
345
+ iex(1)> Calculator.Supervisor.start_link
346
+ 0 から始めまーす
347
+ {:ok, #PID<0.71.0>}
348
+ iex(2)> Calculator.plus(1)
349
+ 0 に 1 を足しまーす
350
+ :ok
351
+ iex(3)> Calculator.plus(3)
352
+ 1 に 3 を足しまーす
353
+ :ok
354
+ iex(4)> Calculator.plus("bom!")
355
+ 4 に bom! を足しまーす
356
+ 4 で終わりまーす
357
+ :ok
358
+ 0 から始めまーす
359
+ iex(5)> Calculator.plus(2)
360
+ 0 に 2 を足しまーす
361
+ :ok
362
+ ```
363
+
364
+ # 障害をのりきって動く
365
+
366
+ 「最初は 0 で初期化,値がきたら今までの値と足し合わせる.
367
+ エラーになったら合計を表示する.
368
+ その後また初期化から処理を再開する」
369
+ というモジュールを作る.
370
+
371
+ (`・肉・)< **障害のりきれた!**
372
+
373
+ # バージョンアップ中にも動く
374
+
375
+ 「ver0では数字が1ずつ増える.ver1では数字が10ずつ増える.
376
+ そのときデータの流れは止めない」
377
+
378
+ 好きな言語で実装してみよう
379
+
380
+ # バージョンアップ中にも動く
381
+
382
+ ```ruby
383
+ # version_up-0.exs
384
+ defmodule Successor do
385
+ use GenServer
386
+
387
+ @vsn "0"
388
+
389
+ def start_link, do: GenServer.start_link(__MODULE__, 0, name: __MODULE__)
390
+ def next_number, do: GenServer.call(__MODULE__, :next_number)
391
+
392
+ def handle_call(:next_number, _from, state) do
393
+ reply = state + 1
394
+ {:reply, reply, reply}
395
+ end
396
+ end
397
+ ```
398
+
399
+ # バージョンアップ中にも動く
400
+
401
+ ```ruby
402
+ # version_up-1.exs
403
+ defmodule Successor do
404
+ use GenServer
405
+
406
+ @vsn "1"
407
+
408
+ def start_link, do: GenServer.start_link(__MODULE__, 0, name: __MODULE__)
409
+ def next_number, do: GenServer.call(__MODULE__, :next_number)
410
+
411
+ def handle_call(:next_number, _from, state) do
412
+ reply = state + 10
413
+ {:reply, reply, reply}
414
+ end
415
+
416
+ def code_change("0", state, extra) do
417
+ IO.puts "バージョン 0 から #{@vsn} にコード書き変えます.今の値は #{state}"
418
+ {:ok, state * 10}
419
+ end
420
+ end
421
+ ```
422
+
423
+ # バージョンアップ中にも動く
424
+
425
+ ```
426
+ $ iex -r version_up-0.exs
427
+ iex(1)> Successor.start_link
428
+ {:ok, #PID<0.68.0>}
429
+ iex(2)> Successor.next_number
430
+ 1
431
+ iex(3)> Successor.next_number
432
+ 2
433
+ iex(4)> :sys.suspend Successor
434
+ :ok
435
+ iex(5)> c("version_up-1.exs")
436
+ version_up-1.exs:1: warning: redefining module Successor
437
+ version_up-1.exs:14: warning: variable extra is unused
438
+ [Successor]
439
+ iex(6)> :sys.change_code Successor, Successor, "0", []
440
+ バージョン 0 から 1 にコード書き変えます.今の値は 2
441
+ :ok
442
+ iex(7)> :sys.resume Successor
443
+ :ok
444
+ iex(8)> Successor.next_number
445
+ 30
446
+ ```
447
+
448
+ # それなりに速く動作する
449
+
450
+ - Erlang だとプロセスの分離 spawn を多用する
451
+ - Python だとだいたい Thread といえるかな……
452
+
453
+ 多用する spawn はどのくらい速いのか
454
+
455
+ # それなりに速く動作する
456
+
457
+ ```python
458
+ import threading
459
+
460
+ list(map (lambda x:threading.Thread().start(), range(1000000)))
461
+ ```
462
+
463
+ ```
464
+ $ time python3 thread.py
465
+ python3 thread.py 59.94s user 45.48s system 124% cpu 1:24.54 total
466
+ ```
467
+
468
+ # それなりに速く動作する
469
+
470
+ ```ruby
471
+ Enum.map((1..1000000), fn (_x) ->
472
+ spawn(fn ->
473
+ end)
474
+ end)
475
+ ```
476
+
477
+ ```
478
+ $ time elixir --erl "+P 1000000" spawns.exs
479
+ elixir --erl "+P 1000000" fork.exs 5.18s user 8.35s system 148% cpu 9.125 total
480
+ ```
481
+
482
+ # それなりに速く動作する
483
+
484
+ - Python 100 万個のスレッドを作るのに 84.5 秒.
485
+ - ErlangVM 100 万個のプロセス ( スレッドのようなもの ) を作るのに 9.13 秒
486
+
487
+ 10 倍くらい速いみたい
488
+
489
+ # それなりに速く動作する
490
+
491
+ 注意: **ErlangVMは普通のCPU処理は遅いみたいです**
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabbit-slide-niku-erlangvm-for-pythonista
3
+ version: !ruby/object:Gem::Version
4
+ version: 2015.09.12
5
+ platform: ruby
6
+ authors:
7
+ - niku
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-12 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: ErlangVM for Pythonista
28
+ email:
29
+ - niku@niku.name
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".rabbit"
35
+ - README.md
36
+ - Rakefile
37
+ - config.yaml
38
+ - erlangvm-for-pythonista.md
39
+ - pdf/erlangvm-for-pythonista-erlangvm-for-pythonista.pdf
40
+ homepage: http://slide.rabbit-shocker.org/authors/niku/erlangvm-for-pythonista/
41
+ licenses: []
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.4.5.1
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: "蛇とビーム"
63
+ test_files: []