List Benchmarks
filter_map
Mix.install([:benchee])
defmodule Kore do
defp custom_filter_map([], _), do: []
defp custom_filter_map([head | tail], func) do
case func.(head) do
false ->
custom_filter_map(tail, func)
{true, value} ->
[value | custom_filter_map(tail, func)]
end
end
def custom_run(list) do
custom_filter_map(list, fn x ->
if rem(x, 2) == 0 do
{true, x * x}
else
false
end
end)
end
def for(list) do
for x <- list, rem(x, 2) == 0 do
x * x
end
end
def filter_then_map(list) do
list
|> Enum.filter(fn x -> rem(x, 2) == 0 end)
|> Enum.map(fn x -> x * x end)
end
def erlang_filter_then_map(list) do
list = :lists.filter(fn x -> rem(x, 2) == 0 end, list)
:lists.map(fn x -> x * x end, list)
end
def erlang_filtermap(list) do
:lists.filtermap(
fn x ->
if rem(x, 2) == 0 do
{true, x * x}
else
false
end
end,
list
)
end
def reduce(list) do
Enum.reduce(list, [], fn x, acc ->
if rem(x, 2) == 0 do
[x * x | acc]
else
acc
end
end)
|> Enum.reverse()
end
def stream_filter_then_map(list) do
list
|> Stream.filter(fn x -> rem(x, 2) == 0 end)
|> Stream.map(fn x -> x * x end)
|> Enum.to_list()
end
def for_uniq(list) do
for x <- list, uniq: true do
x.name
end
end
def map_then_uniq(list) do
list
|> Enum.map(fn x -> x.name end)
|> Enum.uniq()
end
end
max = 10_000
list = Enum.to_list(1..max)
Benchee.run(%{
"for" => fn ->
Kore.for(list)
end,
"filter.map" => fn ->
Kore.filter_then_map(list)
end,
"erlang filter.map" => fn ->
Kore.erlang_filter_then_map(list)
end,
"erlang filtermap" => fn ->
Kore.erlang_filtermap(list)
end,
"reduce" => fn ->
Kore.reduce(list)
end,
"custom" => fn ->
Kore.custom_run(list)
end,
"stream filter.map" => fn ->
Kore.stream_filter_then_map(list)
end
})
employees =
for _ <- 1..100_000 do
%{name: Enum.random(["Alice", "Bob", "Carol"])}
end
Benchee.run(%{
"for_uniq" => fn ->
Kore.for_uniq(employees)
end,
"map.uniq" => fn ->
Kore.map_then_uniq(employees)
end
})
:erlang.system_info(:emu_flavor)
Results filtermap
Max: 10000
Operating System: macOS
CPU Information: Apple M1
Number of Available Cores: 8
Available memory: 8 GB
Elixir 1.12.0
Erlang 24.0
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 49 s
Benchmarking custom...
Benchmarking erlang filter.map...
Benchmarking erlang filtermap...
Benchmarking filter.map...
Benchmarking for...
Benchmarking reduce...
Benchmarking stream filter.map...
Name ips average deviation median 99th %
reduce 6.51 K 153.49 μs ±4.10% 155 μs 165 μs
custom 5.80 K 172.46 μs ±3.44% 171 μs 194 μs
for 5.63 K 177.70 μs ±9.72% 179 μs 207 μs
erlang filtermap 4.32 K 231.70 μs ±3.84% 232 μs 260 μs
erlang filter.map 4.11 K 243.60 μs ±2.09% 244 μs 257.06 μs
filter.map 3.95 K 253.12 μs ±1.75% 253 μs 268 μs
stream filter.map 1.50 K 665.52 μs ±8.01% 677 μs 827 μs
Comparison:
reduce 6.51 K
custom 5.80 K - 1.12x slower +18.96 μs
for 5.63 K - 1.16x slower +24.20 μs
erlang filtermap 4.32 K - 1.51x slower +78.20 μs
erlang filter.map 4.11 K - 1.59x slower +90.11 μs
filter.map 3.95 K - 1.65x slower +99.63 μs
stream filter.map 1.50 K - 4.34x slower +512.03 μs
JIT
Max: 10000
Operating System: macOS
CPU Information: Apple M1
Number of Available Cores: 8
Available memory: 8 GB
Elixir 1.12.0
Erlang 25.0-rc0
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 49 s
Benchmarking custom...
Benchmarking erlang filter.map...
Benchmarking erlang filtermap...
Benchmarking filter.map...
Benchmarking for...
Benchmarking reduce...
Benchmarking stream filter.map...
Name ips average deviation median 99th %
for 12.49 K 80.08 μs ±14.22% 81.99 μs 102.99 μs
reduce 11.07 K 90.35 μs ±24.50% 82.99 μs 157.99 μs
erlang filtermap 9.24 K 108.23 μs ±18.70% 103.99 μs 163.99 μs
custom 8.95 K 111.79 μs ±23.80% 100.99 μs 194.91 μs
erlang filter.map 6.45 K 155.03 μs ±10.42% 149.99 μs 194.99 μs
filter.map 6.32 K 158.28 μs ±13.42% 149.99 μs 253.99 μs
stream filter.map 2.94 K 339.61 μs ±14.87% 329.99 μs 478.99 μs
Comparison:
for 12.49 K
reduce 11.07 K - 1.13x slower +10.27 μs
erlang filtermap 9.24 K - 1.35x slower +28.15 μs
custom 8.95 K - 1.40x slower +31.71 μs
erlang filter.map 6.45 K - 1.94x slower +74.95 μs
filter.map 6.32 K - 1.98x slower +78.20 μs
stream filter.map 2.94 K - 4.24x slower +259.53 μs
Results mapuniq
JIT
Operating System: macOS
CPU Information: Apple M1
Number of Available Cores: 8
Available memory: 8 GB
Elixir 1.13.4
Erlang 25.0-rc0
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s
Benchmarking for_uniq ...
Benchmarking map.uniq ...
Name ips average deviation median 99th %
for_uniq 332.13 3.01 ms ±5.67% 2.99 ms 3.31 ms
map.uniq 240.29 4.16 ms ±3.06% 4.14 ms 4.52 ms
Comparison:
for_uniq 332.13
map.uniq 240.29 - 1.38x slower +1.15 ms