3
2

非同期でSystem.cmdを使ってping砲

Last updated at Posted at 2024-09-06

検証目的

  • Task.asyncの検証です
  • System.cmdの処理を分散したい
  • 待ち時間を減らしたい
  • すべて実行するまで待ちたい

ソース

Task.asyncの有り無しで時間比較します

defmodule ConcurrentExperiment do
  @moduledoc """
  Documentation for `ConcurrentExperiment`.
  """

  @doc """
  Hello world.

  ## Examples

      iex> ConcurrentExperiment.hello()
      :ok

  """
  def hello do
    run_ping = :timer.tc(fn -> run_ping() end)
    run_ping_async = :timer.tc(fn -> run_ping_async() end)

    run_ping |> IO.inspect()
    run_ping_async |> IO.inspect()

    {run_ping_time, _} = run_ping
    {run_ping_async_time, _} = run_ping_async

    run_ping_time / run_ping_async_time |> IO.inspect()

    :ok
  end

  def run_ping_async() do
    task =
    1..10
    |> Enum.map(& ping_async("192.168.0.#{&1}"))

    task
    |> Enum.map(& Task.await(&1))
    |> results_output()
  end

  def run_ping() do
    1..10
    |> Enum.map(& ping("192.168.0.#{&1}"))
    |> results_output()
  end

  def transform_output({results, _}) do
    results
    |> String.split(" ")
    |> Enum.at(1)
  end

  def results_output(results) do
    results
    |> Enum.filter(fn {_ , ok} -> ok == 0 end)
    |> Enum.map(& transform_output(&1))
  end

  def ping_async(ip) do
    Task.async(fn ->
      System.cmd("ping",  ~w"-w 1 #{ip}")
    end)
  end

  def ping(ip) do
      System.cmd("ping",  ~w"-w 1 #{ip}")
  end

end

結果

{10056036,
 ["192.168.0.1", "192.168.0.4", "192.168.0.6", "192.168.0.9", "192.168.0.10"]}
{1008590,
 ["192.168.0.1", "192.168.0.4", "192.168.0.6", "192.168.0.9", "192.168.0.10"]}
9.970390346919958

約 9.97倍の速度差がでました
これは、ping時に存在しないホストがあると待機するためです
非同期にすることで高速化できます

ソース(github)

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2