當你生來是一個beam虛擬機裏的進程,你所熟悉的一切是在這個世界上,每一個進程能夠相互收發消息。你所不知道的事是,每一個進程並非同時執行的,而是由調度器進行調度。oop
有一天,爲了探究真實的世界,你竊取了beam虛擬機的bif(built in function)之一: erlang:trace
的使用權。有了它,能夠監控到任意一個進程的一舉一動。ui
要想使用它,首先須要一個進程去處理它發出來的 trace 消息:spa
defmodule N1 do def start do spawn(&loop/0) end defp loop do receive do msg -> IO.inspect(msg) loop() end end end
而後,找一個「受害者」。你找到了這我的畜無害的進程,它每2秒會給本身打個招呼,而後就沉沉睡去。在它安眠的時候,cpu是否還會把關心它呢?code
defmodule N2 do def start do spawn(&loop/0) end defp loop do :timer.sleep(2000) send(self(), :hi) receive do :hi -> loop() end end end
你悄悄開啓了實驗進程
iex(1)> n2 = N2.start #PID<0.155.0> iex(2)> n1 = N1.start #PID<0.157.0> iex(3)> :erlang.trace n2, true, [:all, {:tracer, n1}] 1 {:trace_ts, #PID<0.155.0>, :in, {:timer, :sleep, 1}, 3, {1604, 420048, 633876}} {:trace_ts, #PID<0.155.0>, :receive, :timeout, 3, {1604, 420048, 633890}} {:trace_ts, #PID<0.155.0>, :send, :hi, #PID<0.155.0>, 3, {1604, 420048, 633898}} {:trace_ts, #PID<0.155.0>, :receive, :hi, 3, {1604, 420048, 633902}} {:trace_ts, #PID<0.155.0>, :out, {:timer, :sleep, 1}, 3, {1604, 420048, 633916}} {:trace_ts, #PID<0.155.0>, :in, {:timer, :sleep, 1}, 3, {1604, 420050, 635069}} {:trace_ts, #PID<0.155.0>, :receive, :timeout, 3, {1604, 420050, 635079}} {:trace_ts, #PID<0.155.0>, :send, :hi, #PID<0.155.0>, 3, {1604, 420050, 635086}} {:trace_ts, #PID<0.155.0>, :receive, :hi, 3, {1604, 420050, 635090}} {:trace_ts, #PID<0.155.0>, :out, {:timer, :sleep, 1}, 3, {1604, 420050, 635098}}
祕密信息被打印在了IO設備上,記錄了一次次的 receive 和 send。最重要的是:in
(進入調度器)和 out
(離開調度器)的記錄。你很清楚地看見,在進程沉睡的2秒裏,屬於它的cpu時間被竊取了。你第一次證明了曾經的猜測:這是一個楚門的世界。虛擬機