So Iv been working on Morphlings diff algo to create a dom differential to send over the wire wasting as little CPU/Memory as possible and wanted to talk about a point when dealing with binaries.
This is how you shoot yourself in the foot and then turn around and say BEAM/Erlang/Elixir is very slow and bad.
100x Slower code with linear slowdown
fn_chunk = fn(bin,parts)->
size = byte_size(bin)
segment_size = div(size, parts)+1
{chunks,_} = Enum.reduce_while(0..(parts*2), {[], bin}, fn(idx,{a,bin})->
piece = String.slice(bin, 0, segment_size)
case piece do
"" -> {:halt, {a,bin}}
_ ->
a = a ++ [%{old_pos: idx*segment_size, size: segment_size, binary: piece}]
{:cont, {a, String.slice(bin, segment_size, size)}}
end
end)
chunks
end
Fast code
fn_chunk = fn(bin,parts)->
size = byte_size(bin)
segment_size = div(size, parts)+1
{chunks,_} = Enum.reduce_while(0..(parts*2), {[], 0}, fn(_,{a,idx})->
to_take = min(byte_size(bin)-idx, segment_size)
piece = :binary.part(bin, idx, to_take)
case piece do
"" -> {:halt, {a,bin}}
_ ->
a = a ++ [%{old_pos: idx, size: to_take, binary: piece}]
{:cont, {a, idx+to_take}}
end
end)
chunks
end
What this piece does is, it splits a binary into x amount of equal parts. On a binary of size 20k, the above slow code takes 100ms, on a 5k size binary takes 43ms.
The fast code takes 0-1ms on a 20k size binary.
What is the difference?