3

以下は、バイナリのバイトを追加する単純な実装です。eprofによると遅いです(合計時間の約10%かかります-主に多くの呼び出しが原因ですbinary:part/3)。

これはどのように最適化できますか?

calc_checksum(Packet) when is_binary(Packet)->  
    calc_checksum(Packet, 0).

calc_checksum(<<>>, Acc) -> 
    Acc band 16#FFFF;

calc_checksum(Packet, Acc) when is_binary(Packet) ->        
    W = binary:decode_unsigned(binary:part(Packet, 0, 2), little),
    NextAcc = Acc + W,
    NextBytes = binary:part(Packet, byte_size(Packet), -(byte_size(Packet)-2)),
    calc_checksum(NextBytes, NextAcc).
4

3 に答える 3

8

よりエレガントな解決策は次のとおりです。

calc_checksum(<<W:16/little,Rest/bytes>>, Acc0) ->
    Acc1 = Acc0 + W,
    calc_checksum(Rest, Acc1);
calc_checksum(<<>>, Acc) -> Acc band 16#FFFF.

バイナリに奇数のバイトが含まれている場合、このコードはエラーを生成します。通常、パターンマッチングを使用すると、よりエレガントなコードが得られます。

于 2012-08-07T00:47:35.477 に答える
2

複数の値を一度に処理すると、 Robert の ソリューションよりも少し高速化することさえできます。

calc_checksum(<<W1:16/little, W2:16/little, W3:16/little, W4:16/little, Rest/bytes>>, Acc)->
    calc_checksum(Rest, Acc+W1+W2+W3+W4);
calc_checksum(<<W:16/little,Rest/bytes>>, Acc) ->
    calc_checksum(Rest, Acc+W);
calc_checksum(<<>>, Acc) -> Acc band 16#FFFF.
于 2012-08-09T21:09:09.950 に答える
2

関数を呼び出す代わりにパターン マッチングを使用するbinaryと、シェルで試した疑似ベンチマークで速度が 2 倍になるようです。このようなもの:

calc_checksum(Packet, Acc) when is_binary(Packet) ->
    <<W:16/little, NextBytes/binary>> = Packet,
    NextAcc = Acc + W,
    calc_checksum(NextBytes, NextAcc).

(私は間違っているかもしれませんが、 に設定NextAccすると同等の結果が得られるはず(Acc + W) band 16#FFFFです。これにより、これを非常に大きなバイナリで実行すると、bignum が回避されるはずです。)

于 2012-08-06T17:19:44.080 に答える