Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

FFmpeg Benchmark

articles/ffmpeg_benchmark.livemd

FFmpeg Benchmark

Setup

Mix.install([
  :benchee,
  :req
])
Resolving Hex dependencies...
Dependency resolution completed:
New:
  benchee 1.1.0
  castore 0.1.15
  deep_merge 1.0.0
  finch 0.9.1
  hpax 0.1.1
  jason 1.3.0
  mime 2.0.2
  mint 1.4.1
  nimble_options 0.4.0
  nimble_pool 0.2.6
  req 0.2.1
  statistex 1.0.0
  telemetry 1.0.0
* Getting benchee (Hex package)
* Getting req (Hex package)
* Getting finch (Hex package)
* Getting jason (Hex package)
* Getting mime (Hex package)
* Getting castore (Hex package)
* Getting mint (Hex package)
* Getting nimble_options (Hex package)
* Getting nimble_pool (Hex package)
* Getting telemetry (Hex package)
* Getting hpax (Hex package)
* Getting deep_merge (Hex package)
* Getting statistex (Hex package)
==> nimble_options
Compiling 3 files (.ex)
Generated nimble_options app
==> hpax
Compiling 4 files (.ex)
Generated hpax app
==> nimble_pool
Compiling 2 files (.ex)
Generated nimble_pool app
==> deep_merge
Compiling 2 files (.ex)
Generated deep_merge app
===> Analyzing applications...
===> Compiling telemetry
==> jason
Compiling 10 files (.ex)
Generated jason app
==> castore
Compiling 1 file (.ex)
Generated castore app
==> mint
Compiling 1 file (.erl)
Compiling 19 files (.ex)
Generated mint app
==> finch
Compiling 11 files (.ex)
Generated finch app
==> statistex
Compiling 3 files (.ex)
Generated statistex app
==> benchee
Compiling 44 files (.ex)
Generated benchee app
==> mime
Compiling 1 file (.ex)
Generated mime app
==> req
Compiling 4 files (.ex)
Generated req app
:ok

Benchmark

require Logger

filename_list = [{"6MB", "dVVDpHKN7PFs_0Z8WDi71Q==.mp4"}, {"57MB", "gRyc01oTZ9WtGoZX7hA1bQ=="}]
timestamps_list = [{10, 1..10}, {30, 1..30}]

for {file_size, filename} <- filename_list, {timestamp_size, timestamps} <- timestamps_list do
  url_path = "https://storage.googleapis.com/momenti-dev-public-0/content/#{filename}"

  create_temp_dir = fn ->
    unique_name = "#{:os.system_time(:millisecond)}-#{:erlang.unique_integer([:positive])}"
    dir = Path.join(System.tmp_dir!(), unique_name)
    File.mkdir_p(dir)

    dir
  end

  dir = create_temp_dir.()

  to_local_file = fn url_path ->
    %{body: file} = Req.get!(url_path)
    file_path = "#{dir}/#{filename}"
    :ok = File.write!(file_path, file)

    file_path
  end

  local_1by1 = fn ->
    file_path = to_local_file.(url_path)

    timestamps
    |> Enum.map(fn timestamp ->
      args = ~w(-y -i #{file_path} -ss #{timestamp} -frames:v 1 -q:v 2 #{dir}/#{timestamp}.jpg)

      System.cmd("ffmpeg", args)
    end)
  end

  local_1by1_parallel = fn ->
    file_path = to_local_file.(url_path)

    timestamps
    |> Enum.map(fn timestamp ->
      Task.async(fn ->
        args = ~w(-y -i #{file_path} -ss #{timestamp} -frames:v 1 -q:v 2 #{dir}/#{timestamp}.jpg)

        System.cmd("ffmpeg", args)
      end)
    end)
    |> Task.await_many(:infinity)
  end

  local_all = fn ->
    file_path = to_local_file.(url_path)

    args =
      timestamps
      |> Enum.with_index()
      |> Enum.map(fn {timestamp, index} ->
        ~w[-ss #{timestamp} -i #{file_path} -map #{index}:v -frames:v 1 -q:v 2 #{dir}/#{timestamp}.jpg]
      end)
      |> List.flatten()

    System.cmd("ffmpeg", ["-y" | args])
  end

  remote_1by1 = fn ->
    timestamps
    |> Enum.map(fn timestamp ->
      args = ~w(-y -i #{url_path} -ss #{timestamp} -frames:v 1 -q:v 2 #{dir}/#{timestamp}.jpg)

      System.cmd("ffmpeg", args)
    end)
  end

  remote_1by1_parallel = fn ->
    timestamps
    |> Enum.map(fn timestamp ->
      Task.async(fn ->
        args = ~w(-y -i #{url_path} -ss #{timestamp} -frames:v 1 -q:v 2 #{dir}/#{timestamp}.jpg)

        System.cmd("ffmpeg", args)
      end)
    end)
    |> Task.await_many(:infinity)
  end

  remote_all = fn ->
    args =
      timestamps
      |> Enum.with_index()
      |> Enum.map(fn {timestamp, index} ->
        ~w[-ss #{timestamp} -i #{url_path} -map #{index}:v -frames:v 1 -q:v 2 #{dir}/#{timestamp}.jpg]
      end)
      |> List.flatten()

    System.cmd("ffmpeg", ["-y" | args])
  end

  Benchee.run(
    %{
      "#{file_size}, #{timestamp_size} from local 1 by 1" => local_1by1,
      "#{file_size}, #{timestamp_size} from local 1 by 1 parallel" => local_1by1_parallel,
      "#{file_size}, #{timestamp_size} from local all at once" => local_all,
      "#{file_size}, #{timestamp_size} from remote 1 by 1" => remote_1by1,
      "#{file_size}, #{timestamp_size} from remote 1 by 1 parallel" => remote_1by1_parallel,
      "#{file_size}, #{timestamp_size} from remote all at once" => remote_all
    },
    time: 20
  )
end

:ok
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
Number of Available Cores: 8
Available memory: 32 GB
Elixir 1.13.1
Erlang 24.1.6

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 20 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 2.20 min

Benchmarking 6MB, 10 f rom remote 1 by 1 parallel ...
Benchmarking 6MB, 10 from local 1 by 1 ...
Benchmarking 6MB, 10 from local 1 by 1 parallel ...
Benchmarking 6MB, 10 from local all at once ...
Benchmarking 6MB, 10 from remote 1 by 1 ...
Benchmarking 6MB, 10 from remote all at once ...

Name                                           ips        average  deviation         median         99th %
6MB, 10 f rom remote 1 by 1 parallel          0.43         2.32 s     ±4.48%         2.31 s         2.51 s
6MB, 10 from local all at once                0.37         2.72 s     ±6.85%         2.69 s         3.14 s
6MB, 10 from local 1 by 1 parallel            0.32         3.16 s     ±2.00%         3.17 s         3.27 s
6MB, 10 from local 1 by 1                    0.182         5.51 s    ±30.04%         4.72 s         7.99 s
6MB, 10 from remote all at once              0.112         8.96 s     ±1.08%         8.95 s         9.06 s
6MB, 10 from remote 1 by 1                  0.0938        10.66 s     ±0.60%        10.66 s        10.71 s

Comparison: 
6MB, 10 f rom remote 1 by 1 parallel          0.43
6MB, 10 from local all at once                0.37 - 1.17x slower +0.40 s
6MB, 10 from local 1 by 1 parallel            0.32 - 1.36x slower +0.84 s
6MB, 10 from local 1 by 1                    0.182 - 2.37x slower +3.19 s
6MB, 10 from remote all at once              0.112 - 3.86x slower +6.64 s
6MB, 10 from remote 1 by 1                  0.0938 - 4.60x slower +8.34 s
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
Number of Available Cores: 8
Available memory: 32 GB
Elixir 1.13.1
Erlang 24.1.6

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 20 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 2.20 min

Benchmarking 6MB, 30 f rom remote 1 by 1 parallel ...
Benchmarking 6MB, 30 from local 1 by 1 ...
Benchmarking 6MB, 30 from local 1 by 1 parallel ...
Benchmarking 6MB, 30 from local all at once ...
Benchmarking 6MB, 30 from remote 1 by 1 ...
Benchmarking 6MB, 30 from remote all at once ...

Name                                           ips        average  deviation         median         99th %
6MB, 30 from local all at once                0.26         3.81 s     ±2.81%         3.79 s         3.96 s
6MB, 30 f rom remote 1 by 1 parallel        0.0909        11.00 s     ±2.14%        11.00 s        11.17 s
6MB, 30 from local 1 by 1 parallel          0.0883        11.32 s     ±1.98%        11.32 s        11.48 s
6MB, 30 from local 1 by 1                   0.0496        20.15 s     ±0.00%        20.15 s        20.15 s
6MB, 30 from remote all at once             0.0376        26.58 s     ±0.00%        26.58 s        26.58 s
6MB, 30 from remote 1 by 1                  0.0228        43.80 s     ±0.00%        43.80 s        43.80 s

Comparison: 
6MB, 30 from local all at once                0.26
6MB, 30 f rom remote 1 by 1 parallel        0.0909 - 2.89x slower +7.19 s
6MB, 30 from local 1 by 1 parallel          0.0883 - 2.97x slower +7.51 s
6MB, 30 from local 1 by 1                   0.0496 - 5.29x slower +16.34 s
6MB, 30 from remote all at once             0.0376 - 6.97x slower +22.77 s
6MB, 30 from remote 1 by 1                  0.0228 - 11.49x slower +39.99 s
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
Number of Available Cores: 8
Available memory: 32 GB
Elixir 1.13.1
Erlang 24.1.6

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 20 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 2.20 min

Benchmarking 57MB, 10 f rom remote 1 by 1 parallel ...
Benchmarking 57MB, 10 from local 1 by 1 ...
Benchmarking 57MB, 10 from local 1 by 1 parallel ...
Benchmarking 57MB, 10 from local all at once ...
Benchmarking 57MB, 10 from remote 1 by 1 ...
Benchmarking 57MB, 10 from remote all at once ...

Name                                            ips        average  deviation         median         99th %
57MB, 10 from local all at once                3.98      251.45 ms    ±50.87%      227.27 ms     1281.51 ms
57MB, 10 from local 1 by 1 parallel            3.76      266.28 ms     ±5.34%      263.96 ms      325.48 ms
57MB, 10 from remote all at once               3.46      288.65 ms     ±1.99%      288.28 ms      306.71 ms
57MB, 10 f rom remote 1 by 1 parallel          2.77      361.12 ms     ±7.17%      355.84 ms      460.75 ms
57MB, 10 from local 1 by 1                     2.00      499.40 ms     ±5.07%      493.40 ms      606.59 ms
57MB, 10 from remote 1 by 1                    0.34     2949.16 ms     ±3.31%     2915.70 ms     3157.82 ms

Comparison: 
57MB, 10 from local all at once                3.98
57MB, 10 from local 1 by 1 parallel            3.76 - 1.06x slower +14.82 ms
57MB, 10 from remote all at once               3.46 - 1.15x slower +37.20 ms
57MB, 10 f rom remote 1 by 1 parallel          2.77 - 1.44x slower +109.66 ms
57MB, 10 from local 1 by 1                     2.00 - 1.99x slower +247.95 ms
57MB, 10 from remote 1 by 1                    0.34 - 11.73x slower +2697.71 ms
Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
Number of Available Cores: 8
Available memory: 32 GB
Elixir 1.13.1
Erlang 24.1.6

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 20 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 2.20 min

Benchmarking 57MB, 30 f rom remote 1 by 1 parallel ...
Benchmarking 57MB, 30 from local 1 by 1 ...
Benchmarking 57MB, 30 from local 1 by 1 parallel ...
Benchmarking 57MB, 30 from local all at once ...
Benchmarking 57MB, 30 from remote 1 by 1 ...
Benchmarking 57MB, 30 from remote all at once ...

Name                                            ips        average  deviation         median         99th %
57MB, 30 from local all at once                4.22      236.82 ms    ±11.73%      229.00 ms      358.15 ms
57MB, 30 from remote all at once               3.40      294.36 ms     ±5.04%      291.95 ms      381.91 ms
57MB, 30 from local 1 by 1 parallel            2.39      418.57 ms     ±6.57%      413.34 ms      498.16 ms
57MB, 30 f rom remote 1 by 1 parallel          1.73      577.59 ms     ±7.70%      572.09 ms      722.55 ms
57MB, 30 from local 1 by 1                     0.95     1055.04 ms     ±3.77%     1040.64 ms     1198.30 ms
57MB, 30 from remote 1 by 1                   0.115     8708.27 ms     ±0.48%     8686.19 ms     8756.89 ms

Comparison: 
57MB, 30 from local all at once                4.22
57MB, 30 from remote all at once               3.40 - 1.24x slower +57.53 ms
57MB, 30 from local 1 by 1 parallel            2.39 - 1.77x slower +181.75 ms
57MB, 30 f rom remote 1 by 1 parallel          1.73 - 2.44x slower +340.77 ms
57MB, 30 from local 1 by 1                     0.95 - 4.45x slower +818.22 ms
57MB, 30 from remote 1 by 1                   0.115 - 36.77x slower +8471.45 ms
:ok