Skip to content

Instantly share code, notes, and snippets.

@evadne
Last active January 5, 2024 10:57
Show Gist options
  • Save evadne/33805e13f1d84eb2e32f0d1e1a376899 to your computer and use it in GitHub Desktop.
Save evadne/33805e13f1d84eb2e32f0d1e1a376899 to your computer and use it in GitHub Desktop.
Reversing Binaries in Elixir
defmodule Benchmarker do
def run(title, module, function, size \\ 1024, iterations \\ 100) do
times = for (_ <- 1 .. iterations) do
data = :crypto.strong_rand_bytes(size)
{duration, _value} = :timer.tc fn ->
apply(module, function, [data])
end
duration
end
avg = Enum.sum(times) / iterations
min = Enum.reduce(times, &Kernel.min/2)
max = Enum.reduce(times, &Kernel.max/2)
IO.puts "#{title} avg #{avg}µs / min #{min}µs / max #{max}µs"
end
end
defmodule ListReverse do
#
# https://elixir-lang.slackarchive.io/general/page-100/ts-1504036208000433
#
def reverse(binary) do
binary |> :binary.bin_to_list |> Enum.reverse |> :binary.list_to_bin
end
end
defmodule EncodeDecodeEndiannessReverse do
#
# https://elixir-lang.slackarchive.io/general/page-100/ts-1504039301000460
#
def reverse(binary) do
binary |> :binary.decode_unsigned(:little) |> :binary.encode_unsigned(:big)
end
end
defmodule ElixirBinaryReverse do
#
# https://github.com/comboy/elixir-binary/blob/master/lib/binary.ex#L54
#
def reverse(binary) when is_binary(binary), do: do_reverse(binary, <<>>)
defp do_reverse(<<>>, acc), do: acc
defp do_reverse(<< x :: binary-size(1), bin :: binary >>, acc), do: do_reverse(bin, x <> acc)
end
defmodule IOListReverse do
#
# https://elixir-lang.slackarchive.io/general/page-100/ts-1504040788000314
#
def reverse(binary) when is_binary(binary), do: do_reverse(binary, [])
defp do_reverse(<<>>, iolist), do: iolist |> IO.iodata_to_binary
defp do_reverse(<<chunk::size(8), rest::binary>>, iolist), do: do_reverse(rest, [chunk|iolist])
end
for (size <- 1 .. 512) do
binary_size = size * 1024
IO.puts("#{binary_size}bytes")
Benchmarker.run("ListReverse", ListReverse, :reverse, binary_size)
Benchmarker.run("ElixirBinaryReverse", ElixirBinaryReverse, :reverse, binary_size)
Benchmarker.run("EncodeDecodeEndiannessReverse", EncodeDecodeEndiannessReverse, :reverse, binary_size)
Benchmarker.run("IOListReverse", IOListReverse, :reverse, binary_size)
IO.puts("\n")
end
$ elixir -v
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Elixir 1.5.0
$ elixir reverse.exs
1024bytes
ListReverse avg 11.28µs / min 6µs / max 24µs
ElixirBinaryReverse avg 218.95µs / min 175µs / max 437µs
EncodeDecodeEndiannessReverse avg 2.59µs / min 1µs / max 34µs
IOListReverse avg 14.25µs / min 13µs / max 19µs
2048bytes
ListReverse avg 19.58µs / min 11µs / max 39µs
ElixirBinaryReverse avg 590.19µs / min 504µs / max 1291µs
EncodeDecodeEndiannessReverse avg 4.26µs / min 3µs / max 16µs
IOListReverse avg 32.24µs / min 25µs / max 35µs
3072bytes
ListReverse avg 28.98µs / min 16µs / max 97µs
ElixirBinaryReverse avg 849.68µs / min 626µs / max 1637µs
EncodeDecodeEndiannessReverse avg 6.58µs / min 5µs / max 31µs
IOListReverse avg 45.52µs / min 39µs / max 116µs
4096bytes
ListReverse avg 51.03µs / min 22µs / max 110µs
ElixirBinaryReverse avg 1191.76µs / min 838µs / max 2200µs
EncodeDecodeEndiannessReverse avg 7.67µs / min 6µs / max 11µs
IOListReverse avg 59.56µs / min 57µs / max 129µs
5120bytes
ListReverse avg 52.52µs / min 28µs / max 132µs
ElixirBinaryReverse avg 1316.38µs / min 1136µs / max 2112µs
EncodeDecodeEndiannessReverse avg 8.97µs / min 8µs / max 12µs
IOListReverse avg 79.74µs / min 76µs / max 135µs
6144bytes
ListReverse avg 68.01µs / min 33µs / max 220µs
ElixirBinaryReverse avg 1702.35µs / min 1398µs / max 2952µs
EncodeDecodeEndiannessReverse avg 13.05µs / min 9µs / max 48µs
IOListReverse avg 97.84µs / min 85µs / max 164µs
7168bytes
ListReverse avg 80.03µs / min 38µs / max 221µs
ElixirBinaryReverse avg 2242.42µs / min 1731µs / max 3868µs
EncodeDecodeEndiannessReverse avg 12.7µs / min 11µs / max 25µs
IOListReverse avg 123.21µs / min 116µs / max 364µs
8192bytes
ListReverse avg 76.89µs / min 44µs / max 222µs
ElixirBinaryReverse avg 2651.06µs / min 2126µs / max 4184µs
EncodeDecodeEndiannessReverse avg 17.62µs / min 13µs / max 38µs
IOListReverse avg 144.82µs / min 122µs / max 252µs
9216bytes
ListReverse avg 97.82µs / min 51µs / max 283µs
ElixirBinaryReverse avg 2737.13µs / min 2461µs / max 4310µs
EncodeDecodeEndiannessReverse avg 16.19µs / min 14µs / max 30µs
IOListReverse avg 135.76µs / min 110µs / max 252µs
10240bytes
ListReverse avg 102.36µs / min 56µs / max 250µs
ElixirBinaryReverse avg 3380.27µs / min 2902µs / max 7774µs
EncodeDecodeEndiannessReverse avg 17.71µs / min 16µs / max 34µs
IOListReverse avg 146.43µs / min 139µs / max 246µs
11264bytes
ListReverse avg 122.44µs / min 62µs / max 290µs
ElixirBinaryReverse avg 3571.39µs / min 3286µs / max 5754µs
EncodeDecodeEndiannessReverse avg 18.36µs / min 17µs / max 24µs
IOListReverse avg 155.46µs / min 143µs / max 357µs
12288bytes
ListReverse avg 138.09µs / min 67µs / max 363µs
ElixirBinaryReverse avg 4264.24µs / min 3724µs / max 10531µs
EncodeDecodeEndiannessReverse avg 19.64µs / min 18µs / max 24µs
IOListReverse avg 247.94µs / min 189µs / max 445µs
13312bytes
ListReverse avg 176.45µs / min 75µs / max 457µs
ElixirBinaryReverse avg 4813.14µs / min 4033µs / max 13187µs
EncodeDecodeEndiannessReverse avg 23.67µs / min 19µs / max 52µs
IOListReverse avg 211.47µs / min 182µs / max 465µs
14336bytes
ListReverse avg 182.89µs / min 83µs / max 343µs
ElixirBinaryReverse avg 5599.34µs / min 4651µs / max 17518µs
EncodeDecodeEndiannessReverse avg 24.22µs / min 22µs / max 62µs
IOListReverse avg 222.13µs / min 169µs / max 1614µs
15360bytes
ListReverse avg 170.61µs / min 87µs / max 466µs
ElixirBinaryReverse avg 5996.69µs / min 5175µs / max 14345µs
EncodeDecodeEndiannessReverse avg 25.45µs / min 23µs / max 47µs
IOListReverse avg 239.96µs / min 209µs / max 1718µs
16384bytes
ListReverse avg 211.94µs / min 93µs / max 833µs
ElixirBinaryReverse avg 6923.24µs / min 5704µs / max 23778µs
EncodeDecodeEndiannessReverse avg 27.35µs / min 25µs / max 40µs
IOListReverse avg 248.79µs / min 207µs / max 433µs
17408bytes
ListReverse avg 210.82µs / min 96µs / max 627µs
ElixirBinaryReverse avg 7291.71µs / min 6716µs / max 10133µs
EncodeDecodeEndiannessReverse avg 32.23µs / min 28µs / max 83µs
IOListReverse avg 266.58µs / min 233µs / max 1642µs
18432bytes
ListReverse avg 302.28µs / min 108µs / max 1998µs
ElixirBinaryReverse avg 8644.68µs / min 7164µs / max 29917µs
EncodeDecodeEndiannessReverse avg 31.64µs / min 28µs / max 96µs
IOListReverse avg 458.31µs / min 227µs / max 2061µs
19456bytes
ListReverse avg 289.93µs / min 111µs / max 669µs
ElixirBinaryReverse avg 8947.74µs / min 7843µs / max 24326µs
EncodeDecodeEndiannessReverse avg 31.39µs / min 29µs / max 56µs
IOListReverse avg 324.25µs / min 300µs / max 437µs
20480bytes
ListReverse avg 254.55µs / min 118µs / max 688µs
ElixirBinaryReverse avg 10266.29µs / min 8872µs / max 45452µs
EncodeDecodeEndiannessReverse avg 35.59µs / min 31µs / max 72µs
IOListReverse avg 359.5µs / min 287µs / max 1766µs
21504bytes
ListReverse avg 267.76µs / min 124µs / max 1668µs
ElixirBinaryReverse avg 10956.76µs / min 9127µs / max 46210µs
EncodeDecodeEndiannessReverse avg 37.58µs / min 35µs / max 61µs
IOListReverse avg 359.84µs / min 319µs / max 1778µs
22528bytes
ListReverse avg 264.76µs / min 129µs / max 1684µs
ElixirBinaryReverse avg 12571.07µs / min 10486µs / max 49007µs
EncodeDecodeEndiannessReverse avg 38.87µs / min 35µs / max 82µs
IOListReverse avg 369.2µs / min 328µs / max 697µs
23552bytes
ListReverse avg 349.16µs / min 138µs / max 855µs
ElixirBinaryReverse avg 13702.08µs / min 12025µs / max 16531µs
EncodeDecodeEndiannessReverse avg 42.88µs / min 37µs / max 117µs
IOListReverse avg 373.01µs / min 336µs / max 971µs
24576bytes
ListReverse avg 315.76µs / min 141µs / max 897µs
ElixirBinaryReverse avg 16896.68µs / min 12733µs / max 61839µs
EncodeDecodeEndiannessReverse avg 47.48µs / min 38µs / max 423µs
IOListReverse avg 383.29µs / min 345µs / max 642µs
25600bytes
ListReverse avg 288.13µs / min 146µs / max 468µs
ElixirBinaryReverse avg 16532.1µs / min 13953µs / max 70851µs
EncodeDecodeEndiannessReverse avg 46.55µs / min 40µs / max 91µs
IOListReverse avg 421.08µs / min 354µs / max 870µs
26624bytes
ListReverse avg 325.52µs / min 153µs / max 562µs
ElixirBinaryReverse avg 17389.98µs / min 15177µs / max 33669µs
EncodeDecodeEndiannessReverse avg 51.5µs / min 40µs / max 776µs
IOListReverse avg 424.08µs / min 363µs / max 1840µs
27648bytes
ListReverse avg 310.86µs / min 162µs / max 508µs
ElixirBinaryReverse avg 19089.23µs / min 16323µs / max 80723µs
EncodeDecodeEndiannessReverse avg 49.22µs / min 43µs / max 147µs
IOListReverse avg 418.83µs / min 372µs / max 1866µs
28672bytes
ListReverse avg 322.86µs / min 166µs / max 712µs
ElixirBinaryReverse avg 22164.03µs / min 17393µs / max 85063µs
EncodeDecodeEndiannessReverse avg 54.55µs / min 44µs / max 233µs
IOListReverse avg 479.14µs / min 372µs / max 1053µs
29696bytes
ListReverse avg 327.86µs / min 171µs / max 914µs
ElixirBinaryReverse avg 22002.56µs / min 18456µs / max 79229µs
EncodeDecodeEndiannessReverse avg 55.63µs / min 45µs / max 126µs
IOListReverse avg 683.27µs / min 364µs / max 939µs
30720bytes
ListReverse avg 534.5µs / min 184µs / max 1446µs
ElixirBinaryReverse avg 24820.67µs / min 19417µs / max 260384µs
EncodeDecodeEndiannessReverse avg 59.82µs / min 48µs / max 132µs
IOListReverse avg 654.54µs / min 498µs / max 2189µs
31744bytes
ListReverse avg 524.47µs / min 187µs / max 1046µs
ElixirBinaryReverse avg 32961.49µs / min 20424µs / max 245010µs
EncodeDecodeEndiannessReverse avg 63.59µs / min 50µs / max 695µs
IOListReverse avg 562.86µs / min 489µs / max 1020µs
32768bytes
ListReverse avg 406.65µs / min 189µs / max 1732µs
ElixirBinaryReverse avg 25483.54µs / min 22194µs / max 76336µs
EncodeDecodeEndiannessReverse avg 72.18µs / min 51µs / max 1659µs
IOListReverse avg 540.45µs / min 497µs / max 1105µs
33792bytes
ListReverse avg 374.52µs / min 200µs / max 995µs
ElixirBinaryReverse avg 28571.68µs / min 23927µs / max 80112µs
EncodeDecodeEndiannessReverse avg 63.19µs / min 54µs / max 132µs
IOListReverse avg 740.56µs / min 522µs / max 1495µs
34816bytes
ListReverse avg 700.01µs / min 224µs / max 1327µs
ElixirBinaryReverse avg 28789.39µs / min 23619µs / max 105229µs
EncodeDecodeEndiannessReverse avg 57.6µs / min 50µs / max 87µs
IOListReverse avg 580.15µs / min 515µs / max 1172µs
35840bytes
ListReverse avg 658.56µs / min 212µs / max 1262µs
ElixirBinaryReverse avg 30905.4µs / min 26413µs / max 104325µs
EncodeDecodeEndiannessReverse avg 62.24µs / min 56µs / max 106µs
IOListReverse avg 562.41µs / min 523µs / max 805µs
36864bytes
ListReverse avg 437.74µs / min 220µs / max 1221µs
ElixirBinaryReverse avg 31324.7µs / min 25800µs / max 98197µs
EncodeDecodeEndiannessReverse avg 67.02µs / min 57µs / max 165µs
IOListReverse avg 615.57µs / min 533µs / max 2188µs
37888bytes
ListReverse avg 426.62µs / min 224µs / max 1098µs
ElixirBinaryReverse avg 33581.56µs / min 27411µs / max 93293µs
EncodeDecodeEndiannessReverse avg 65.78µs / min 54µs / max 130µs
IOListReverse avg 587.98µs / min 557µs / max 1004µs
38912bytes
ListReverse avg 494.81µs / min 223µs / max 2816µs
ElixirBinaryReverse avg 33823.14µs / min 29014µs / max 105475µs
EncodeDecodeEndiannessReverse avg 63.89µs / min 56µs / max 105µs
IOListReverse avg 610.12µs / min 508µs / max 2061µs
39936bytes
ListReverse avg 481.33µs / min 231µs / max 1948µs
ElixirBinaryReverse avg 37381.01µs / min 30712µs / max 117811µs
EncodeDecodeEndiannessReverse avg 69.28µs / min 62µs / max 111µs
IOListReverse avg 661.55µs / min 560µs / max 2669µs
40960bytes
ListReverse avg 488.86µs / min 241µs / max 1118µs
ElixirBinaryReverse avg 37384.78µs / min 31563µs / max 124126µs
EncodeDecodeEndiannessReverse avg 73.65µs / min 66µs / max 155µs
IOListReverse avg 735.47µs / min 585µs / max 1620µs
41984bytes
ListReverse avg 532.21µs / min 252µs / max 1288µs
ElixirBinaryReverse avg 41592.44µs / min 34539µs / max 168248µs
EncodeDecodeEndiannessReverse avg 73.13µs / min 65µs / max 137µs
IOListReverse avg 662.48µs / min 577µs / max 1659µs
43008bytes
ListReverse avg 525.35µs / min 253µs / max 1400µs
ElixirBinaryReverse avg 42198.1µs / min 34590µs / max 133351µs
EncodeDecodeEndiannessReverse avg 76.82µs / min 67µs / max 133µs
IOListReverse avg 655.26µs / min 570µs / max 1225µs
44032bytes
ListReverse avg 560.14µs / min 247µs / max 1420µs
ElixirBinaryReverse avg 42445.36µs / min 37178µs / max 137053µs
EncodeDecodeEndiannessReverse avg 73.73µs / min 67µs / max 101µs
IOListReverse avg 634.36µs / min 579µs / max 1357µs
45056bytes
ListReverse avg 562.18µs / min 253µs / max 1256µs
ElixirBinaryReverse avg 45221.23µs / min 37172µs / max 137744µs
EncodeDecodeEndiannessReverse avg 78.58µs / min 72µs / max 128µs
IOListReverse avg 708.91µs / min 622µs / max 1986µs
46080bytes
ListReverse avg 548.07µs / min 274µs / max 1874µs
ElixirBinaryReverse avg 47539.79µs / min 39983µs / max 153474µs
EncodeDecodeEndiannessReverse avg 76.78µs / min 66µs / max 146µs
IOListReverse avg 711.16µs / min 614µs / max 1441µs
47104bytes
ListReverse avg 561.57µs / min 286µs / max 1326µs
ElixirBinaryReverse avg 48946.26µs / min 40526µs / max 160503µs
EncodeDecodeEndiannessReverse avg 81.16µs / min 73µs / max 138µs
IOListReverse avg 692.18µs / min 622µs / max 2143µs
48128bytes
ListReverse avg 854.93µs / min 292µs / max 1626µs
ElixirBinaryReverse avg 50468.47µs / min 42589µs / max 175154µs
EncodeDecodeEndiannessReverse avg 85.94µs / min 77µs / max 141µs
IOListReverse avg 1252.25µs / min 614µs / max 2311µs
49152bytes
ListReverse avg 950.32µs / min 299µs / max 1939µs
ElixirBinaryReverse avg 70767.18µs / min 47875µs / max 706703µs
EncodeDecodeEndiannessReverse avg 87.94µs / min 79µs / max 144µs
IOListReverse avg 1050.5µs / min 803µs / max 1585µs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment