当BERT是二进制字符串时如何解码BERT

时间:2011-03-07 21:35:10

标签: erlang

我通过查询字符串传递给Erlang BERT。我正在通过带有http_bin选项的gen_tcp读取它,所以它就像这样到达<<“131,104,1,100,0,2,104,105”>>。这几乎是正确的,因为我想用binary_to_term / 2解码它。但是binary_to_term / 2想要二进制二进制,而不是字符串二进制(它想要<<< 131,104,1,100,0,2,104,105>><<<“131,104,1,100,0,2,104,105”>>)

我可以将它解析为正确的形式。

parse(Source) ->
    Bins = binary:split(Source, <<",">>, [global]),
    parse(Bins, []).
parse([H | T], Acc) ->
    parse(T, [list_to_integer(binary_to_list(H)) | Acc]);
parse([], Acc) ->
    list_to_binary(lists:reverse(Acc)).

但这似乎很复杂,并且比我希望的要慢(~5k / sec,每个都是200字节)。还提出了一些基于io_lib的东西:fread / 2,但它并没有好多少,看起来仍然很尴尬。

  1. 在某处可能有BIF或NIF吗?

  2. 如果没有,是否有更好的方法来加快上述速度?

2 个答案:

答案 0 :(得分:0)

对于它的价值,一个替代解决方案 - 可能更慢,但可能更少临时,取决于品味 - 是将其视为解析Erlang子集的问题,对于哪些工具存在:

parse(Source) ->
  case erl_scan:string(Source++" .") of
    {ok, Tokens, _} ->
      case erl_parse:parse_term(Tokens) of
        {ok, Bin} when is_binary(Bin) -> % Only accept binary literals.
          Bin;
        _ -> error(badarg)
      end;
    _ -> error(badarg)
  end.

在这种情况下可能有点过分,但没有比原始解决方案更多的代码。

答案 1 :(得分:0)

使用此代码,您可以使用本机(HiPE)解析高达75MB / s,使用字节代码解析高达17MB / s:

-module(str_to_bin).

-export([str_to_bin/1]).

str_to_bin(Bin) when is_binary(Bin) ->
  str_to_bin(Bin, <<>>).

-define(D(X), X >= $0, X =< $9 ).

-define(C(X), (X band 2#1111)).

str_to_bin(<<X,Y,Z,Rest/binary>>, Acc)
    when ?D(X), ?D(Y), ?D(Z) ->
  str_to_bin_(Rest, <<Acc/binary, (?C(X)*100 + ?C(Y)*10 + ?C(Z))>>);
str_to_bin(<<Y,Z,Rest/binary>>, Acc)
    when ?D(Y), ?D(Z) ->
  str_to_bin_(Rest, <<Acc/binary, (?C(Y)*10 + ?C(Z))>>);
str_to_bin(<<Z,Rest/binary>>, Acc)
    when ?D(Z) ->
  str_to_bin_(Rest, <<Acc/binary, ?C(Z)>>).

-compile({inline, [str_to_bin_/2]}).

str_to_bin_(<<>>, Acc) -> Acc;
str_to_bin_(<<$,, Rest/binary>>, Acc) -> str_to_bin(Rest, Acc).