当你生来是一个beam虚拟机里的进程,你所熟悉的一切是在这个世界上,每个进程可以相互收发消息。你所不知道的事是,每个进程并不是同时执行的,而是由调度器进行调度。
有一天,为了探究真实的世界,你窃取了beam虚拟机的bif(built in function)之一: erlang:trace
的使用权。有了它,可以监控到任意一个进程的一举一动。
要想使用它,首先需要一个进程去处理它发出来的 trace 消息:
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是否还会把关心它呢?
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时间被窃取了。你第一次证实了曾经的猜想:这是一个楚门的世界。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。