[erlang-questions] Binary no-copy
Bob Cowdery
bob@REDACTED
Thu Mar 17 19:31:45 CET 2011
Thanks. More or less what I thought that the only copy is in the append
operation. The one liner is the big one in terms of time but I will
profile the whole thing eventually. I don't think your solution does
quite the same thing as the sent block must be exactly the correct size
not >= but I appreciate the kind of structure you are using with small
clauses is more elegant.
Bob
On 17/03/2011 17:11, Per Gustafsson wrote:
> It will copy binaries, but essentially the state binary will act like
> a growable array, pre-allocating space to grow in, so there will be
> some copying , but it will be linear in the size of the resulting
> array.
> It might be a little bit faster to rewrite this as shown below. The
> reason I think this might be faster is that you do not create a
> temporary samples array that just gets copied. Whether this is faster
> or not in reality is of course a matter of benchmarking.
>
> %% Constants
> %% Input scale factor
> -define (S, (1 bsl 23) - 1).
> %% Block size for DSP (interleaved I and Q)
> -define (BlockSz, 1024).
> %% Samples in a Metis frame (interleaved I and Q)
> -define (MetisSmpls, 63).
> %% Bytes in a float
> -define (FloatSz, 4).
> %% Size of binary for given block size
> -define (BinSz, ?BlockSz*2*?FloatSz*?MetisSmpls).
>
> do_decode_frame(Frame, State) ->
> %% Separate the command bytes from the frame data
> <<C1:8, C2:8, C3:8, C4:8, C5:8, Rest/binary>> = Frame,
> decode_samples(Rest, State).
>
> decode_samples(Frame, State) when size(State) >= ?BinSz ->
> dsp:process_block(State),
> decode_samples(Frame, <<>>);
> decode_samples(<<I:24/big-signed, Q:24/big-signed, _M:16/big-signed,
> Rest/binary>>, State) ->
> decode_samples(<<State/binary, (I/?S):32/float, (Q/?S):32/float>>;
> decode_samples(<<>>, State) ->
> {ok, State}.
>
> 2011/3/17 Bob Cowdery <bob@REDACTED>
>> Hi,
>>
>> Am I correct in thinking that the code fragments below will not copy any
>> binary data. I've not tested the function yet so it may have bugs but
>> I'm interested in whether it will be optimal in efficiency. State starts
>> off as an empty binary. Frames are decoded and placed in a block. There
>> are not an integral number of frames to a block. The function
>> dsp:process_block() is in another gen-server.
>>
>> Thanks
>> Bob
>>
>> %% Constants
>> %% Input scale factor
>> -define (S, (1 bsl 23) - 1).
>> %% Block size for DSP (interleaved I and Q)
>> -define (BlockSz, 1024).
>> %% Samples in a Metis frame (interleaved I and Q)
>> -define (MetisSmpls, 63).
>> %% Bytes in a float
>> -define (FloatSz, 4).
>> %% Size of binary for given block size
>> -define (BinSz, ?BlockSz*2*?FloatSz*?MetisSmpls).
>>
>> do_decode_frame(Frame, State) ->
>> %% Separate the command bytes from the frame data
>> <<C1:8, C2:8, C3:8, C4:8, C5:8, Rest/binary>> = Frame,
>> %% What's left now is <<I:24, Q:24, M:16 ..repeated 63 times.. >>
>> %% This one liner converts the I and Q to scaled floats
>> Samples = << <<(I/?S):32/float, (Q/?S):32/float>> ||
>> <<I:24/big-signed, Q:24/big-signed, _M:16/big-signed>> <= Rest >>,
>> CurrentSz = size(State),
>> FrameSz = size(Samples),
>> if
>> (CurrentSz + FrameSz) < ?BinSz ->
>> NewState = <<State/binary, Samples/binary>>;
>> true ->
>> %% Binary part of this transfer
>> CutAt = ?BinSz - CurrentSz - 1,
>> Bp = binary_part(Samples, {0, CutAt}),
>> %% Binary part of remainder
>> Br = binary_part(Samples, {CutAt, FrameSz - CutAt}),
>> %% Process this block
>> dsp:process_block(<<State/binary, Bp/binary>>),
>> NewState = Br
>> end,
>> {ok, NewState}.
>>
>> ________________________________________________________________
>> erlang-questions (at) erlang.org mailing list.
>> See http://www.erlang.org/faq.html
>> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>>
More information about the erlang-questions
mailing list