Skip to content

Instantly share code, notes, and snippets.

@cr0t
Last active April 5, 2024 17:40
Show Gist options
  • Save cr0t/95d0ac8e3ebe186e6b83436c286b14c0 to your computer and use it in GitHub Desktop.
Save cr0t/95d0ac8e3ebe186e6b83436c286b14c0 to your computer and use it in GitHub Desktop.
Elixir benchmark of two solution approaches for Luhn task from Exercism.org
Mix.install([:benchee])
defmodule LuhnChecksum do
defguard is_even(x) when rem(x, 2) == 0
def with_reverse(digits) do
digits
|> Enum.reverse()
|> Enum.with_index(1)
|> Enum.map(fn
{d, idx} when is_even(idx) -> luhn_double(d)
{d, _} -> d
end)
|> Enum.sum()
end
def with_reduce(digits) when is_even(length(digits)) do
digits
|> Enum.with_index()
|> Enum.reduce(0, fn
{d, idx}, acc when is_even(idx) -> acc + luhn_double(d)
{d, _}, acc -> acc + d
end)
end
def with_reduce(digits), do: with_reduce([0 | digits])
defp luhn_double(digit) do
case 2 * digit do
d when d > 9 -> d - 9
d -> d
end
end
end
short_num = [1, 0, 9]
long_num = [2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4]
# ensure that all the functions from above return the same result
IO.inspect([
LuhnChecksum.with_reduce(short_num) == LuhnChecksum.with_reverse(short_num),
LuhnChecksum.with_reduce(long_num) == LuhnChecksum.with_reverse(long_num),
], label: "===> All functions return the same result")
Benchee.run(
%{
"with_reduce-long" => fn -> LuhnChecksum.with_reduce(long_num) end,
"with_reverse-long" => fn -> LuhnChecksum.with_reverse(long_num) end,
"with_reduce-short" => fn -> LuhnChecksum.with_reduce(short_num) end,
"with_reverse-short" => fn -> LuhnChecksum.with_reverse(short_num) end
},
time: 5,
memory_time: 5,
print: [fast_warning: false]
)
===> All functions return the same result: [true, true]
Operating System: macOS
CPU Information: Apple M3 Pro
Number of Available Cores: 11
Available memory: 18 GB
Elixir 1.16.2
Erlang 26.2.2
JIT enabled: true
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 5 s
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 48 s
Benchmarking with_reduce-long ...
Benchmarking with_reduce-short ...
Benchmarking with_reverse-long ...
Benchmarking with_reverse-short ...
Calculating statistics...
Formatting results...
Name ips average deviation median 99th %
with_reverse-short 10.94 M 91.42 ns ±32616.82% 42 ns 125 ns
with_reduce-long 9.31 M 107.45 ns ±2594.47% 95.80 ns 133.40 ns
with_reduce-short 8.33 M 120.00 ns ±29068.65% 42 ns 167 ns
with_reverse-long 5.82 M 171.69 ns ±18079.33% 125 ns 250 ns
Comparison:
with_reverse-short 10.94 M
with_reduce-long 9.31 M - 1.18x slower +16.04 ns
with_reduce-short 8.33 M - 1.31x slower +28.59 ns
with_reverse-long 5.82 M - 1.88x slower +80.27 ns
Memory usage statistics:
Name Memory usage
with_reverse-short 216 B
with_reduce-long 480 B - 2.22x memory usage +264 B
with_reduce-short 176 B - 0.81x memory usage -40 B
with_reverse-long 864 B - 4.00x memory usage +648 B
**All measurements for memory usage were the same**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment