由於 BEAM VM 的特性,debug 時我們可以選擇關閉指定正在執行的 process 或是特定的指揮串,而不是只有直接關掉整個 instance 這個選擇。
這邊示範一下其中一種在 BEAM 內除錯的方式
使用 Process.info
與 Process.list
這個組合就可以讓我們抓取最耗資源的 process
假如現在系統有一個沒效率的函式來加 1 到指定數字的加總
defmodule Calc do
def sum(n), do: sum(n, 1)
defp sum(0, acc), do: acc
defp sum(n, acc), do: sum(n - 1, n + acc)
end
在 iex 裡我們使用 spawn 來模擬他在別的 process 執行,並給他一個很大的數字,讓他跑不完
# iex
spawn fn -> Calc.sum(10000000000) end
可以發現 就算有一個需要執行非常久的 process ,iex 本身還是可以正常執行,因為 scadular 在輪流執行 process 時,會有一定的 reduction 限制,不會永遠卡在一個 process 上。這個特點讓 BEAM 系統可以比較溫和的處理這方面的問題。
當然雖然衝擊不明顯但有問題還是要解決,除了我們可以在 observer 裡面看到這個特別耗資源的 process 之外
我們也可在 iex 裡,用 Process.list 與 Process.info 的組合來撈出最多 reductions 數的 process
list = Process.list() \
|> Enum.map(fn pid -> {Process.info(pid, :reductions) |> elem(1), pid} end) \
|> Enum.sort_by(fn {reductions, _} -> reductions end, :desc)
[
{6468120000, #PID<0.114.0>},
{360699, #PID<0.116.0>},
{226790, #PID<0.50.0>},
{127569, #PID<0.108.0>},
{125492, #PID<0.130.0>},
{83841, #PID<0.117.0>},
{72692, #PID<0.45.0>},
{34977, #PID<0.66.0>},
{32731, #PID<0.70.0>},
{27719, #PID<0.120.0>},
{18495, #PID<0.115.0>},
{11182, #PID<0.11.0>},
...
接著用 Process.exit 將它關閉就可以了
iex(7)> {_, pid} = hd(list)
{8039888000, #PID<0.114.0>}
iex(8)> Process.exit(pid, :kill)
true