Hey all,
As the title says, what do you think is the most efficient way to fill a binary with all constant values? I usually do the following:
for _i <- 1..n, into: "", do: <<0xFF>>
But when using a large-ish number for n
, such as 10_000, it takes a couple of seconds to fill the buffer (on my low-powered Nerves device).
The following is actually noticeably faster:
(for _i <- 1..n, do: 0xFF) |> :erlang.list_to_binary
Some timings:
iex(23)> :timer.tc(fn ->
...(23)> for _i <- 1..10_000, into: "", do: <<0xFF>>
...(23)> end)
{1184934,
<<255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, ...>>}
iex(24)> :timer.tc(fn ->
...(24)> (for _i <- 1..10_000, do: 0xFF) |> :erlang.list_to_binary
...(24)> end)
{64366,
<<255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, ...>>}
That’s a big difference - 1.1 seconds vs 64ms!
I assume the reason for the first one being so slow is because each iteration of the for comprehension does a binary concatenation, whereas the second version appends to the linked list, then accumulates everything at the end into the binary.
This has me wondering - is this the best method for creating large binaries with constant values, or is there something better?