Erlang模式匹配位串

时间:2011-04-28 02:26:13

标签: performance erlang pattern-matching decode bitstring

我正在编写代码来解码来自二进制协议的消息。每种消息类型都分配有1字节类型标识符,每条消息都带有此类型ID。消息都以包含5个字段的公共标头开头。我的API很简单:

decoder:decode(Bin :: binary()) -> my_message_type() | {error, binary()}`

我的第一直觉是通过为每种消息类型编写一个解码函数来严重依赖模式匹配,并在有趣的参数中完全解码该消息类型

decode(<<Hdr1:8, ?MESSAGE_TYPE_ID_X:8, Hdr3:8, Hdr4:8, Hdr5:32, 
         TypeXField1:32, TypeXFld2:32, TypeXFld3:32>>) ->
    #message_x{hdr1=Hdr1, hdr3=Hdr3 ... fld4=TypeXFld3};

decode(<<Hdr1:8, ?MESSAGE_TYPE_ID_Y:8, Hdr3:8, Hdr4:8, Hdr5:32, 
         TypeYField1:32, TypeYFld2:16, TypeYFld3:4, TypeYFld4:32
         TypeYFld5:64>>) ->
    #message_y{hdr1=Hdr1, hdr3=Hdr3 ... fld5=TypeYFld5}.

请注意,虽然消息的前5个字段在结构上相同,但后面的字段因每种消息类型而异。

我有大约20种消息类型,因此有20种类似于上面的功能。我用这种结构多次解码完整的消息?这是惯用的吗?我只是解码函数头中的消息类型字段然后解码消息正文中的完整消息会更好吗?

2 个答案:

答案 0 :(得分:8)

只是同意你的风格是非常惯用的Erlang。除非您认为解码更清晰,否则不要将解码拆分为单独的部分。有时,进行这种类型的分组可能更合乎逻辑。

编译器是智能的,并且编译模式匹配的方式不会多次解码消息。它将首先解码前两个字段(字节),然后使用第二个字段的值(消息类型)来确定它将如何处理消息的其余部分。无论二进制文件的公共部分有多长,这都有效。

因此,他们不需要尝试通过将解码分成单独的部分来“帮助”编译器,它不会使其更有效。再次,只有在它使您的代码更清晰时才这样做。

答案 1 :(得分:7)

您当前的方法是惯用的Erlang,所以继续朝着这个方向前进。不要担心性能,Erlang编译器在这里做得很好。如果你的消息是完全相同的格式,你可以为它编写宏,但它应该在引擎盖下生成相同的代码。无论如何使用宏通常会导致更糟糕的可维护性。只是为了好奇,为什么在所有字段完全相同的情况下生成不同的记录类型?替代方法是将消息类型从常量转换为Erlang原子并将其存储在一种记录类型中。