Mix.install([
:kino_benchee,
:peep
])
defmodule Curr do
@moduledoc """
A helper module for writing modules that implement the `Peep.Buckets`
behavior, with custom bucket boundaries.
For an example, look at the source of `Peep.Buckets.PowersOfTen`.
"""
defmacro __using__(opts) do
dbg Module.attributes_in(__CALLER__.module)
buckets =
Keyword.fetch!(opts, :buckets)
|> Code.eval_quoted([], __CALLER__)
|> elem(0)
|> :lists.usort()
unless Enum.all?(buckets, &is_number/1) do
raise ArgumentError, "expected buckets to be a list of numbers, got: #{buckets}"
end
number_of_buckets = length(buckets)
quote do
@behaviour Peep.Buckets
@impl true
def config(_), do: %{}
@impl true
def number_of_buckets(_), do: unquote(number_of_buckets)
@impl true
unquote(bucket_for_ast(buckets))
@impl true
unquote(upper_bound_ast(buckets))
def all(samples) do
Enum.each(samples, &bucket_for(&1, []))
end
end
end
## Bucket binary search
defp bucket_for_ast(buckets) do
int_buckets =
buckets
|> Enum.map(&ceil/1)
|> Enum.with_index()
|> Enum.dedup_by(&elem(&1, 0))
float_buckets =
buckets
|> Enum.map(&(&1 * 1.0))
|> Enum.with_index()
length = length(buckets)
variable = Macro.var(:x, nil)
int_length = length(int_buckets)
int_tree = build_bucket_tree(int_buckets, int_length, length, variable)
float_length = length(float_buckets)
float_tree = build_bucket_tree(float_buckets, float_length, length, variable)
quote do
def bucket_for(unquote(variable), _) when is_integer(unquote(variable)) do
unquote(int_tree)
end
def bucket_for(unquote(variable), _) when is_float(unquote(variable)) do
unquote(float_tree)
end
end
# |> tap(&IO.puts(Code.format_string!(Macro.to_string(&1))))
end
defp build_bucket_tree([{bound, lval}], 1, rval, variable) do
quote do
case unquote(variable) do
x when x < unquote(bound) ->
unquote(lval)
_ ->
unquote(rval)
end
end
end
defp build_bucket_tree([{lbound, lval}, {rbound, mval}], 2, rval, variable) do
quote do
case unquote(variable) do
x when x < unquote(lbound) ->
unquote(lval)
x when x < unquote(rbound) ->
unquote(mval)
_ ->
unquote(rval)
end
end
end
defp build_bucket_tree(bounds, length, rval, variable) do
llength = div(length, 2)
rlength = length - llength - 1
{lbounds, rbounds} = Enum.split(bounds, llength)
[{bound, lval} | rbounds] = rbounds
quote do
case unquote(variable) do
x when x < unquote(bound) ->
unquote(build_bucket_tree(lbounds, llength, lval, variable))
_ ->
unquote(build_bucket_tree(rbounds, rlength, rval, variable))
end
end
end
## Upper bound
defp upper_bound_ast(buckets) do
bucket_defns =
for {boundary, bucket_idx} <- Enum.with_index(buckets) do
quote do
def upper_bound(unquote(bucket_idx), _), do: unquote(int_to_float_string(boundary))
end
end
final_defn =
quote do
def upper_bound(_, _), do: "+Inf"
end
bucket_defns ++ [final_defn]
end
defp int_to_float_string(int) do
to_string(int * 1.0)
end
end
{:module, Curr, <<70, 79, 82, 49, 0, 0, 32, ...>>, {:int_to_float_string, 1}}
defmodule Fin do
@moduledoc """
A helper module for writing modules that implement the `Peep.Buckets`
behavior, with custom bucket boundaries.
For an example, look at the source of `Peep.Buckets.PowersOfTen`.
"""
defmacro __using__(opts) do
quote bind_quoted: [buckets: Keyword.fetch!(opts, :buckets)] do
@behaviour Peep.Buckets
require Fin
buckets = :lists.usort(buckets)
len = length(buckets)
unless Enum.all?(buckets, &is_number/1) do
raise ArgumentError, "expected buckets to be a list of numbers, got: #{buckets}"
end
@impl true
def config(_), do: %{}
@impl true
def number_of_buckets(_), do: unquote(len)
@impl true
int_buckets =
buckets
|> Enum.map(&ceil/1)
|> Enum.with_index()
|> Enum.dedup_by(&elem(&1, 0))
float_buckets =
buckets
|> Enum.map(&(&1 * 1.0))
|> Enum.with_index()
if len < 32 do
for {top, idx} <- int_buckets do
def bucket_for(val, _) when is_integer(val) and val < unquote(top), do: unquote(idx)
end
for {top, idx} <- float_buckets do
def bucket_for(val, _) when is_float(val) and val < unquote(top), do: unquote(idx)
end
def bucket_for(_, _), do: unquote(length(buckets))
else
def bucket_for(val, _) when is_integer(val) do
Fin.build_tree(unquote(int_buckets), unquote(len), val)
end
def bucket_for(val, _) when is_float(val) do
Fin.build_tree(unquote(float_buckets), unquote(len), val)
end
end
@impl true
def upper_bound(_, _)
for {boundary, bucket_idx} <- Enum.with_index(buckets) do
def upper_bound(unquote(bucket_idx), _), do: unquote(to_string(boundary * 1.0))
end
def upper_bound(_, _), do: "+Inf"
def all(samples) do
Enum.each(samples, &bucket_for(&1, []))
end
end
end
## Bucket binary search
defmacro build_tree(buckets, overflow, var) do
build_bucket_tree(buckets, length(buckets), overflow, var)
end
defp build_bucket_tree([{bound, lval}], 1, rval, variable) do
quote do
case unquote(variable) do
x when x < unquote(bound) ->
unquote(lval)
_ ->
unquote(rval)
end
end
end
defp build_bucket_tree([{lbound, lval}, {rbound, mval}], 2, rval, variable) do
quote do
case unquote(variable) do
x when x < unquote(lbound) ->
unquote(lval)
x when x < unquote(rbound) ->
unquote(mval)
_ ->
unquote(rval)
end
end
end
defp build_bucket_tree(bounds, length, rval, variable) do
llength = div(length, 2)
rlength = length - llength - 1
{lbounds, rbounds} = Enum.split(bounds, llength)
[{bound, lval} | rbounds] = rbounds
quote do
case unquote(variable) do
x when x < unquote(bound) ->
unquote(build_bucket_tree(lbounds, llength, lval, variable))
_ ->
unquote(build_bucket_tree(rbounds, rlength, rval, variable))
end
end
end
end
{:module, Fin, <<70, 79, 82, 49, 0, 0, 21, ...>>, {:build_bucket_tree, 4}}
defmodule Lin do
@moduledoc """
A helper module for writing modules that implement the `Peep.Buckets`
behavior, with custom bucket boundaries.
For an example, look at the source of `Peep.Buckets.PowersOfTen`.
"""
defmacro __using__(opts) do
quote bind_quoted: [buckets: Keyword.fetch!(opts, :buckets)] do
buckets = :lists.usort(buckets)
unless Enum.all?(buckets, &is_number/1) do
raise ArgumentError, "expected buckets to be a list of numbers, got: #{buckets}"
end
@behaviour Peep.Buckets
@impl true
def config(_), do: %{}
@impl true
def number_of_buckets(_), do: unquote(length(buckets))
int_buckets =
buckets
|> Enum.map(&ceil/1)
|> Enum.with_index()
|> Enum.dedup_by(&elem(&1, 0))
float_buckets =
buckets
|> Enum.map(&(&1 * 1.0))
|> Enum.with_index()
max = Enum.max(buckets)
@impl true
for {top, idx} <- int_buckets do
def bucket_for(val, _) when is_integer(val) and val < unquote(top), do: unquote(idx)
end
for {top, idx} <- float_buckets do
def bucket_for(val, _) when is_float(val) and val < unquote(top), do: unquote(idx)
end
def bucket_for(_, _), do: unquote(length(buckets))
@impl true
def upper_bound(_, _)
for {boundary, bucket_idx} <- Enum.with_index(buckets) do
def upper_bound(unquote(bucket_idx), _), do: unquote(to_string(boundary * 1.0))
end
def upper_bound(_, _), do: "+Inf"
def all(samples) do
Enum.each(samples, &bucket_for(&1, []))
end
end
end
## Bucket binary search
def bsearch(tuple, key) do
bsearch(tuple, key, 0, tuple_size(tuple) - 1)
end
defp bsearch(tuple, _key, n, n), do: elem(elem(tuple, n), 1)
defp bsearch(tuple, key, a, b) do
mid = div(b - a, 2) + a
case elem(tuple, mid) do
{v, _} when key < v -> bsearch(tuple, key, a, mid)
_ -> bsearch(tuple, key, mid + 1, b)
end
end
end
{:module, Lin, <<70, 79, 82, 49, 0, 0, 17, ...>>, {:bsearch, 4}}
range = 1..10_000
for {name, step} <- [{Small, 666}, {Mid, 100}, {Large, 10}] do
defmodule Module.concat(Fin, name) do
use Fin, buckets: Enum.to_list(%{range | step: step})
end
defmodule Module.concat(Lin, name) do
use Lin, buckets: Enum.to_list(%{range | step: step})
end
end
warning: variable "step" is unused (if the variable is not meant to be used, prefix it with an underscore)
└─ peep-bench.livemd#cell:armt2gwknf3nnynu:3
[
{:module, Lin.Small,
<<70, 79, 82, 49, 0, 0, 17, 184, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 250, 0, 0, 0, 24, 16,
69, 108, 105, 120, 105, 114, 46, 76, 105, 110, 46, 83, 109, 97, 108, 108, 8, 95, 95, 105, 110,
...>>, {:all, 1}},
{:module, Lin.Mid,
<<70, 79, 82, 49, 0, 0, 45, 172, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 248, 0, 0, 0, 24, 14,
69, 108, 105, 120, 105, 114, 46, 76, 105, 110, 46, 77, 105, 100, 8, 95, 95, 105, 110, 102,
...>>, {:all, 1}},
{:module, Lin.Large,
<<70, 79, 82, 49, 0, 1, 91, 168, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 250, 0, 0, 0, 24, 16,
69, 108, 105, 120, 105, 114, 46, 76, 105, 110, 46, 76, 97, 114, 103, 101, 8, 95, 95, ...>>,
{:all, 1}}
]
Enum.to_list(%{range | step: div(Range.size(range), 15)})
[1, 667, 1333, 1999, 2665, 3331, 3997, 4663, 5329, 5995, 6661, 7327, 7993, 8659, 9325, 9991]
defmodule Curr.Small do
use Curr, buckets: [1, 334, 667, 1000, 1333, 1666, 1999, 2332, 2665, 2998, 3331, 3664, 3997, 4330, 4663, 4996, 5329,
5662, 5995, 6328, 6661, 6994, 7327, 7660, 7993, 8326, 8659, 8992, 9325, 9658, 9991]
end
defmodule Curr.Mid do
use Curr, buckets: [1, 101, 201, 301, 401, 501, 601, 701, 801, 901, 1001, 1101, 1201, 1301, 1401,
1501, 1601, 1701, 1801, 1901, 2001, 2101, 2201, 2301, 2401, 2501, 2601, 2701,
2801, 2901, 3001, 3101, 3201, 3301, 3401, 3501, 3601, 3701, 3801, 3901, 4001,
4101, 4201, 4301, 4401, 4501, 4601, 4701, 4801, 4901, 5001, 5101, 5201, 5301,
5401, 5501, 5601, 5701, 5801, 5901, 6001, 6101, 6201, 6301, 6401, 6501, 6601,
6701, 6801, 6901, 7001, 7101, 7201, 7301, 7401, 7501, 7601, 7701, 7801, 7901,
8001, 8101, 8201, 8301, 8401, 8501, 8601, 8701, 8801, 8901, 9001, 9101, 9201,
9301, 9401, 9501, 9601, 9701, 9801, 9901]
end
defmodule Curr.Large do
use Curr, buckets: [1, 11, 21, 31, 41, 51, 61, 71, 81, 91, 101, 111, 121, 131, 141, 151, 161, 171,
181, 191, 201, 211, 221, 231, 241, 251, 261, 271, 281, 291, 301, 311, 321, 331,
341, 351, 361, 371, 381, 391, 401, 411, 421, 431, 441, 451, 461, 471, 481, 491,
501, 511, 521, 531, 541, 551, 561, 571, 581, 591, 601, 611, 621, 631, 641, 651,
661, 671, 681, 691, 701, 711, 721, 731, 741, 751, 761, 771, 781, 791, 801, 811,
821, 831, 841, 851, 861, 871, 881, 891, 901, 911, 921, 931, 941, 951, 961, 971,
981, 991, 1001, 1011, 1021, 1031, 1041, 1051, 1061, 1071, 1081, 1091, 1101,
1111, 1121, 1131, 1141, 1151, 1161, 1171, 1181, 1191, 1201, 1211, 1221, 1231,
1241, 1251, 1261, 1271, 1281, 1291, 1301, 1311, 1321, 1331, 1341, 1351, 1361,
1371, 1381, 1391, 1401, 1411, 1421, 1431, 1441, 1451, 1461, 1471, 1481, 1491,
1501, 1511, 1521, 1531, 1541, 1551, 1561, 1571, 1581, 1591, 1601, 1611, 1621,
1631, 1641, 1651, 1661, 1671, 1681, 1691, 1701, 1711, 1721, 1731, 1741, 1751,
1761, 1771, 1781, 1791, 1801, 1811, 1821, 1831, 1841, 1851, 1861, 1871, 1881,
1891, 1901, 1911, 1921, 1931, 1941, 1951, 1961, 1971, 1981, 1991, 2001, 2011,
2021, 2031, 2041, 2051, 2061, 2071, 2081, 2091, 2101, 2111, 2121, 2131, 2141,
2151, 2161, 2171, 2181, 2191, 2201, 2211, 2221, 2231, 2241, 2251, 2261, 2271,
2281, 2291, 2301, 2311, 2321, 2331, 2341, 2351, 2361, 2371, 2381, 2391, 2401,
2411, 2421, 2431, 2441, 2451, 2461, 2471, 2481, 2491, 2501, 2511, 2521, 2531,
2541, 2551, 2561, 2571, 2581, 2591, 2601, 2611, 2621, 2631, 2641, 2651, 2661,
2671, 2681, 2691, 2701, 2711, 2721, 2731, 2741, 2751, 2761, 2771, 2781, 2791,
2801, 2811, 2821, 2831, 2841, 2851, 2861, 2871, 2881, 2891, 2901, 2911, 2921,
2931, 2941, 2951, 2961, 2971, 2981, 2991, 3001, 3011, 3021, 3031, 3041, 3051,
3061, 3071, 3081, 3091, 3101, 3111, 3121, 3131, 3141, 3151, 3161, 3171, 3181,
3191, 3201, 3211, 3221, 3231, 3241, 3251, 3261, 3271, 3281, 3291, 3301, 3311,
3321, 3331, 3341, 3351, 3361, 3371, 3381, 3391, 3401, 3411, 3421, 3431, 3441,
3451, 3461, 3471, 3481, 3491, 3501, 3511, 3521, 3531, 3541, 3551, 3561, 3571,
3581, 3591, 3601, 3611, 3621, 3631, 3641, 3651, 3661, 3671, 3681, 3691, 3701,
3711, 3721, 3731, 3741, 3751, 3761, 3771, 3781, 3791, 3801, 3811, 3821, 3831,
3841, 3851, 3861, 3871, 3881, 3891, 3901, 3911, 3921, 3931, 3941, 3951, 3961,
3971, 3981, 3991, 4001, 4011, 4021, 4031, 4041, 4051, 4061, 4071, 4081, 4091,
4101, 4111, 4121, 4131, 4141, 4151, 4161, 4171, 4181, 4191, 4201, 4211, 4221,
4231, 4241, 4251, 4261, 4271, 4281, 4291, 4301, 4311, 4321, 4331, 4341, 4351,
4361, 4371, 4381, 4391, 4401, 4411, 4421, 4431, 4441, 4451, 4461, 4471, 4481,
4491, 4501, 4511, 4521, 4531, 4541, 4551, 4561, 4571, 4581, 4591, 4601, 4611,
4621, 4631, 4641, 4651, 4661, 4671, 4681, 4691, 4701, 4711, 4721, 4731, 4741,
4751, 4761, 4771, 4781, 4791, 4801, 4811, 4821, 4831, 4841, 4851, 4861, 4871,
4881, 4891, 4901, 4911, 4921, 4931, 4941, 4951, 4961, 4971, 4981, 4991, 5001,
5011, 5021, 5031, 5041, 5051, 5061, 5071, 5081, 5091, 5101, 5111, 5121, 5131,
5141, 5151, 5161, 5171, 5181, 5191, 5201, 5211, 5221, 5231, 5241, 5251, 5261,
5271, 5281, 5291, 5301, 5311, 5321, 5331, 5341, 5351, 5361, 5371, 5381, 5391,
5401, 5411, 5421, 5431, 5441, 5451, 5461, 5471, 5481, 5491, 5501, 5511, 5521,
5531, 5541, 5551, 5561, 5571, 5581, 5591, 5601, 5611, 5621, 5631, 5641, 5651,
5661, 5671, 5681, 5691, 5701, 5711, 5721, 5731, 5741, 5751, 5761, 5771, 5781,
5791, 5801, 5811, 5821, 5831, 5841, 5851, 5861, 5871, 5881, 5891, 5901, 5911,
5921, 5931, 5941, 5951, 5961, 5971, 5981, 5991, 6001, 6011, 6021, 6031, 6041,
6051, 6061, 6071, 6081, 6091, 6101, 6111, 6121, 6131, 6141, 6151, 6161, 6171,
6181, 6191, 6201, 6211, 6221, 6231, 6241, 6251, 6261, 6271, 6281, 6291, 6301,
6311, 6321, 6331, 6341, 6351, 6361, 6371, 6381, 6391, 6401, 6411, 6421, 6431,
6441, 6451, 6461, 6471, 6481, 6491, 6501, 6511, 6521, 6531, 6541, 6551, 6561,
6571, 6581, 6591, 6601, 6611, 6621, 6631, 6641, 6651, 6661, 6671, 6681, 6691,
6701, 6711, 6721, 6731, 6741, 6751, 6761, 6771, 6781, 6791, 6801, 6811, 6821,
6831, 6841, 6851, 6861, 6871, 6881, 6891, 6901, 6911, 6921, 6931, 6941, 6951,
6961, 6971, 6981, 6991, 7001, 7011, 7021, 7031, 7041, 7051, 7061, 7071, 7081,
7091, 7101, 7111, 7121, 7131, 7141, 7151, 7161, 7171, 7181, 7191, 7201, 7211,
7221, 7231, 7241, 7251, 7261, 7271, 7281, 7291, 7301, 7311, 7321, 7331, 7341,
7351, 7361, 7371, 7381, 7391, 7401, 7411, 7421, 7431, 7441, 7451, 7461, 7471,
7481, 7491, 7501, 7511, 7521, 7531, 7541, 7551, 7561, 7571, 7581, 7591, 7601,
7611, 7621, 7631, 7641, 7651, 7661, 7671, 7681, 7691, 7701, 7711, 7721, 7731,
7741, 7751, 7761, 7771, 7781, 7791, 7801, 7811, 7821, 7831, 7841, 7851, 7861,
7871, 7881, 7891, 7901, 7911, 7921, 7931, 7941, 7951, 7961, 7971, 7981, 7991,
8001, 8011, 8021, 8031, 8041, 8051, 8061, 8071, 8081, 8091, 8101, 8111, 8121,
8131, 8141, 8151, 8161, 8171, 8181, 8191, 8201, 8211, 8221, 8231, 8241, 8251,
8261, 8271, 8281, 8291, 8301, 8311, 8321, 8331, 8341, 8351, 8361, 8371, 8381,
8391, 8401, 8411, 8421, 8431, 8441, 8451, 8461, 8471, 8481, 8491, 8501, 8511,
8521, 8531, 8541, 8551, 8561, 8571, 8581, 8591, 8601, 8611, 8621, 8631, 8641,
8651, 8661, 8671, 8681, 8691, 8701, 8711, 8721, 8731, 8741, 8751, 8761, 8771,
8781, 8791, 8801, 8811, 8821, 8831, 8841, 8851, 8861, 8871, 8881, 8891, 8901,
8911, 8921, 8931, 8941, 8951, 8961, 8971, 8981, 8991, 9001, 9011, 9021, 9031,
9041, 9051, 9061, 9071, 9081, 9091, 9101, 9111, 9121, 9131, 9141, 9151, 9161,
9171, 9181, 9191, 9201, 9211, 9221, 9231, 9241, 9251, 9261, 9271, 9281, 9291,
9301, 9311, 9321, 9331, 9341, 9351, 9361, 9371, 9381, 9391, 9401, 9411, 9421,
9431, 9441, 9451, 9461, 9471, 9481, 9491, 9501, 9511, 9521, 9531, 9541, 9551,
9561, 9571, 9581, 9591, 9601, 9611, 9621, 9631, 9641, 9651, 9661, 9671, 9681,
9691, 9701, 9711, 9721, 9731, 9741, 9751, 9761, 9771, 9781, 9791, 9801, 9811,
9821, 9831, 9841, 9851, 9861, 9871, 9881, 9891, 9901, 9911, 9921, 9931, 9941,
9951, 9961, 9971, 9981, 9991]
end
[:before_compile, :on_definition, :external_resource, :derive, :typep, :opaque, :spec,
:macrocallback, :behaviour, :type, :dialyzer, :after_verify, :compile, :after_compile, :callback,
:optional_callbacks, :moduledoc]
{:module, Curr.Large, <<70, 79, 82, 49, 0, 1, 172, ...>>, {:all, 1}}
samples = Enum.map(1..100000, fn _ -> Enum.random(1..(range.last + 1000)) end) ++
Enum.map(1..100000, fn _ -> Enum.random(1..(range.last + 1000)) * 0.5 end)
[10021, 7638, 868, 514, 8402, 10906, 170, 22, 2420, 2681, 10242, 1201, 10957, 10944, 2728, 5589,
960, 1915, 1455, 6348, 3564, 7579, 8421, 10845, 7259, 2414, 10570, 8334, 26, 6483, 2364, 5478,
2466, 4528, 2864, 843, 1340, 9531, 9246, 10795, 7054, 3003, 8729, 2019, 8889, 8285, 254, 965, 4392,
5070, ...]
Benchee.run(%{
"curr" => &Curr.Small.all/1,
"fin" => &Fin.Small.all/1,
"lin" => &Lin.Small.all/1,
}, inputs: %{"samples" => samples})
Operating System: macOS
CPU Information: Apple M3 Pro
Number of Available Cores: 12
Available memory: 36 GB
Elixir 1.18.4
Erlang 27.3.4.1
JIT enabled: true
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: samples
Estimated total run time: 21 s
Benchmarking curr with input samples ...
Benchmarking fin with input samples ...
Benchmarking lin with input samples ...
Calculating statistics...
Formatting results...
##### With input samples #####
Name ips average deviation median 99th %
lin 434.51 2.30 ms ±7.52% 2.27 ms 2.74 ms
fin 419.93 2.38 ms ±2.48% 2.38 ms 2.51 ms
curr 331.83 3.01 ms ±2.00% 3.02 ms 3.20 ms
Comparison:
lin 434.51
fin 419.93 - 1.03x slower +0.0799 ms
curr 331.83 - 1.31x slower +0.71 ms
Benchee.run(%{
"curr" => &Curr.Mid.all/1,
"fin" => &Fin.Mid.all/1,
"lin" => &Lin.Mid.all/1,
}, inputs: %{"samples" => samples})
Operating System: macOS
CPU Information: Apple M3 Pro
Number of Available Cores: 12
Available memory: 36 GB
Elixir 1.18.4
Erlang 27.3.4.1
JIT enabled: true
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: samples
Estimated total run time: 21 s
Benchmarking curr with input samples ...
Benchmarking fin with input samples ...
Benchmarking lin with input samples ...
Calculating statistics...
Formatting results...
##### With input samples #####
Name ips average deviation median 99th %
fin 248.60 4.02 ms ±2.72% 4.01 ms 4.38 ms
curr 245.84 4.07 ms ±3.50% 4.04 ms 4.51 ms
lin 159.43 6.27 ms ±2.03% 6.25 ms 6.81 ms
Comparison:
fin 248.60
curr 245.84 - 1.01x slower +0.0451 ms
lin 159.43 - 1.56x slower +2.25 ms
Benchee.run(%{
"curr" => &Curr.Large.all/1,
"fin" => &Fin.Large.all/1,
"lin" => &Lin.Large.all/1,
}, inputs: %{"samples" => samples})
Operating System: macOS
CPU Information: Apple M3 Pro
Number of Available Cores: 12
Available memory: 36 GB
Elixir 1.18.4
Erlang 27.3.4.1
JIT enabled: true
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: samples
Estimated total run time: 21 s
Benchmarking curr with input samples ...
Benchmarking fin with input samples ...
Benchmarking lin with input samples ...
Calculating statistics...
Formatting results...
##### With input samples #####
Name ips average deviation median 99th %
fin 160.73 6.22 ms ±2.64% 6.17 ms 6.82 ms
curr 159.97 6.25 ms ±3.97% 6.23 ms 6.96 ms
lin 20.41 48.99 ms ±2.70% 48.74 ms 55.71 ms
Comparison:
fin 160.73
curr 159.97 - 1.00x slower +0.0295 ms
lin 20.41 - 7.87x slower +42.77 ms