【问题标题】:Erlang pattern matching bitstringsErlang 模式匹配位串
【发布时间】:2011-08-14 08:23:28
【问题描述】:

我正在编写代码来解码来自二进制协议的消息。每个消息类型都分配有一个 1 字节的类型标识符,并且每个消息都带有这个类型 id。消息都以由 5 个字段组成的公共标头开始。我的 API 很简单:

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

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

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 个与上述类似的功能。我是否使用这种结构多次解码完整消息?是地道的吗?我最好只解码函数头中的消息类型字段,然后解码消息正文中的完整消息吗?

【问题讨论】:

  • 元问题:当我编辑这篇文章时,我在预览中得到了漂亮的 erlang 代码着色,但在我发布后呈现的页面中没有。帮忙?
  • 在发布 erlang 代码时也注意到了这一点,可能是 meta 的问题
  • 在 meta 上发布了一个关于语法着色的问题 meta.stackexchange.com/questions/89117/…

标签: performance erlang pattern-matching decode bitstring


【解决方案1】:

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

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

因此,他们无需尝试通过将解码拆分为单独的部分来“帮助”编译器,这不会提高效率。同样,只有当它使您的代码更清晰时才这样做。

【讨论】:

  • 正是我需要在 re: 编译器优化中听到的内容。代码确实更清晰,因为它目前是结构化的。谢谢,罗伯。
【解决方案2】:

您当前的方法是惯用的 Erlang,因此请继续朝这个方向发展。不用担心性能,Erlang 编译器在这里做得很好。如果您的消息格式完全相同,您可以为其编写宏,但它应该在引擎盖下生成相同的代码。无论如何,使用宏通常会导致更差的可维护性。只是出于好奇,为什么当所有记录类型都具有完全相同的字段时,您会生成不同的记录类型?另一种方法是将消息类型从常量转换为 Erlang atom 并将其存储在一种记录类型中。

【讨论】:

  • 我同意这一点。如果您没有简化帖子的结构并且记录都具有相同的格式,请使用原子来区分记录类型 - 一个函数和一个 erlang-record 定义。
  • 对不起 - 我的代码过于简化了。在前 5 个字段之后,消息是不同的。我更新了代码示例,以指示 TypeX 和 TypeY 这两条消息具有不同数量的字段和不同的字段结构。很抱歉造成混乱。
  • @mpm:那么您的代码与 Elang 习语完美匹配。对于代码读者来说,通常更难遵循代码流“匹配这个然后匹配这个然后这个”而不是看这里是一种类型的消息和另一种类型的消息。从长远来看,它甚至更适合维护。在项目的早期阶段之后,您将阅读越来越多的补丁,并且最初的假设可能会发生巨大变化。今天常见的消息不可能在飞蛾或几年内发生,并且每次这样的更改都会导致比您当前的方法更多的代码更改以进行级联匹配。
猜你喜欢
  • 2012-06-13
  • 2014-06-27
  • 2015-09-16
  • 2018-12-08
  • 2011-06-17
  • 2013-08-15
  • 2011-09-29
  • 2010-12-13
  • 2014-07-26
相关资源
最近更新 更多