Created
December 6, 2021 10:56
-
-
Save jarrodmoldrich/b518418a23e9271d83d187a1e3325c1b to your computer and use it in GitHub Desktop.
A benchmark of bit string reversal methods in Elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on a discussion at: | |
// https://elixirforum.com/t/ingest-a-bitstring-from-least-significant-bit/44265/8 | |
Mix.install([{:benchee, "~> 1.0"}]) | |
use Bitwise | |
defmodule ReverseStringMap1 do | |
def lastbit(bitstring) do | |
size = bit_size(bitstring) - 1 | |
<<_head :: size(size), bit :: 1 >> = bitstring | |
bit | |
end | |
def reverse_string_map(bitstring, so_far \\ []) | |
def reverse_string_map(<<>>, so_far), do: Enum.reverse(so_far) | |
def reverse_string_map(bitstring, so_far) do | |
headsize = bit_size(bitstring) - 1 | |
<<head :: size(headsize), bit :: 1 >> = bitstring | |
reverse_string_map(<<head::size(headsize)>>, [bit | so_far]) | |
end | |
end | |
defmodule ReverseStringMap2 do | |
def reverse_string_map(s), do: reverse_string_map(s, [], bit_size(s) - 1) | |
def reverse_string_map(<<>>, _, _), do: [] | |
def reverse_string_map(<<bit::1, _::bits>>, so_far, 0), do: Enum.reverse([bit | so_far]) | |
def reverse_string_map(s, so_far, prefix) do | |
<<_ :: size(prefix), bit::1, _::bits>> = s | |
reverse_string_map(s, [bit | so_far], prefix - 1) | |
end | |
end | |
defmodule ReverseBitString do | |
def reverse_bitstring(value) when is_bitstring(value) do | |
for << bit::1 <- value >>, reduce: {0, 0} do | |
{bits, write_idx} -> | |
{(bit <<< write_idx) ||| bits, write_idx + 1} | |
end | |
|> elem(0) | |
end | |
end | |
defmodule Simple do | |
def reverse_bitstring(value) when is_bitstring(value) do | |
(for << bit::1 <- value >>, into: [], do: bit) | |
|> Enum.reverse() | |
end | |
end | |
values = | |
for _i <- 1..100, | |
do: << (:rand.uniform(65535))::8 >> | |
Benchee.run( | |
%{ | |
"comprehension and reverse" => fn -> | |
for value <- values, | |
do: Simple.reverse_bitstring(value) | |
end, | |
"function style" => fn -> | |
for value <- values, | |
do: ReverseStringMap1.reverse_string_map(value) | |
end, | |
"comprehension w/ reduce + bitwise operations" => fn -> | |
for value <- values, | |
do: ReverseBitString.reverse_bitstring(value) | |
end, | |
"function style 2" => fn -> | |
for value <- values, | |
do: ReverseStringMap2.reverse_string_map(value) | |
end | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment