Last active
July 25, 2019 07:54
-
-
Save tony612/d71bf1cdea7487f452ed17adc7b17f29 to your computer and use it in GitHub Desktop.
Erlang binary parsing comparing
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
# For 0000 0001 0100 0000 1000 1000 | |
# The result is 0b1 + 0b100_0000 + 0b1000 = 73 | |
defmodule BinaryParseFast do | |
def parse(bin) do | |
parse(bin, 0) | |
end | |
# def parse(<<0::1, x::7, _::bits>>, acc), do: acc + x | |
# def parse(<<1::1, x::7, rest::bits>>, acc) do | |
# parse(rest, acc + x) | |
# end | |
# Make it complex on purpose to be consistent with the slow version | |
def parse(bin, acc) do | |
do_parse(bin, acc) | |
end | |
# A byte beginning with 0 means the end, but still need to add the last 7 bits | |
def do_parse(<<0::1, x::7, _::bits>>, acc), do: acc + x | |
# A byte beginning with 1 means there is more data needed to be processed. | |
# and we need to add the last bits | |
def do_parse(<<1::1, x::7, rest::bits>>, acc) do | |
parse(rest, acc + x) | |
end | |
def run(bin) do | |
start = System.monotonic_time(:millisecond) | |
for _ <- 1..10000 do | |
505001 = parse(bin) | |
end | |
finish = System.monotonic_time(:millisecond) | |
finish - start | |
end | |
end | |
bin = | |
1..100 | |
|> Enum.map(fn i -> | |
<<1::1, i::7>> | |
end) | |
|> List.duplicate(100) | |
|> IO.iodata_to_binary() | |
|> Kernel.<>(<<0::1, 1::7>>) | |
duration = BinaryParseFast.run(bin) | |
IO.puts "Total: #{duration}ms" | |
# Total: 1997ms |
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
defmodule BinaryParseSlow do | |
def parse(bin) do | |
parse(bin, 0) | |
end | |
def parse(bin, acc) do | |
case do_parse(bin) do | |
{:nofin, x, rest} -> | |
parse(rest, acc + x) | |
{:fin, x} -> | |
acc + x | |
end | |
end | |
def do_parse(<<0::1, x::7, _::bits>>) do | |
{:fin, x} | |
end | |
def do_parse(<<1::1, x::7, rest::bits>>) do | |
{:nofin, x, rest} | |
end | |
def run(bin) do | |
start = System.monotonic_time(:millisecond) | |
for _ <- 1..10000 do | |
505001 = parse(bin) | |
end | |
finish = System.monotonic_time(:millisecond) | |
finish - start | |
end | |
end | |
bin = | |
1..100 | |
|> Enum.map(fn i -> | |
<<1::1, i::7>> | |
end) | |
|> List.duplicate(100) | |
|> IO.iodata_to_binary() | |
|> Kernel.<>(<<0::1, 1::7>>) | |
duration = BinaryParseSlow.run(bin) | |
IO.puts "Total: #{duration}ms" | |
# Total: 6580ms |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment