需要澄清有关erlang bitstring的匹配上下文

时间:2014-06-04 22:04:35

标签: erlang

我读了efficiency guideerlang-questions mailing list archive& erlang中所有可用的书籍。但我还没有找到有效的准确描述 二进制模式匹配。虽然,我还没有阅读消息来源:)但我希望 那些已经阅读过它们的人会阅读这篇文章。这是我的问题。

  1. erlang二进制文件有多少匹配上下文?

    a)如果我们按顺序匹配二进制的部分而只是一次

    A = <<1,2,3,4>>.
    <<A1,A2,A3,A4>> = A.
    

    我们只有一个二元匹配上下文(从A的开头到结尾),还是四个?

    b)如果我们第一次从开头到结尾依次匹配二进制的部分 并且(从第一次开始到结束再次顺序)

    B = <<1,2,3,4>>.
    <<B1,B2,B3,B4>> = B.
    <<B11,B22,B33,B44>> = B.
    

    我们只有一个匹配上下文,它从B的开头到结尾 B然后再从B的开头移动到B的末尾,

    我们有2个匹配上下文,一个是从B的开头到B的结尾, 和另一个 - 再次从B的开头到B的结尾(因为第一个不能移动 再次开始)

    或者我们有8个匹配上下文?

  2. 根据documentation,如果我写:

    my_binary_to_list(<<H,T/binary>>) ->
        [H|my_binary_to_list(T)];
    my_binary_to_list(<<>>) -> [].
    

    整个递归树只有一个匹配上下文,即使这样 函数不是尾递归的。

    a)我做对了,在这种情况下只有1个匹配上下文吗?

    b)我是否正确,如果我顺序匹配一个二郎二进制(从头到尾) 最后),必须使用哪种递归类型(尾部​​或主体)并不重要?(从二进制匹配效率的角度来看)

    c)如果我要按顺序处理二郎二进制文件怎么办,比方说,我正在旅行 二进制 - 首先我匹配第一个字节,然后是1000,然后是第5个,然后是10001个,然后是第10个......

    在这种情况下,

    d1)如果我使用了body-recursion,那么这个二进制文件的匹配上下文有多少 - 一个或> 1?

    d2)如果我使用了尾递归,那么这个二进制文件的匹配上下文有多少 - 一个或> 1?

  3. 如果我通过尾递归传递一个大的二进制文件(例如1兆字节),是否会复制所有1兆字节的数据?或者只是在调用之间传递了某种指向这个二进制文件开头的指针?

  4. 我匹配哪个二进制文件(无论大小)是否重要?是否会为任何大小的二进制创建匹配上下文或仅为大型二进制创建匹配上下文?

1 个答案:

答案 0 :(得分:0)

我只是erlang的初学者,所以请耐心等待这个答案。

  1.   

    erlang二进制文件有多少匹配上下文?

    a)只创建了一个上下文,但它在该实例中完全被使用,因为没有什么可以匹配,因此它可能不会被重用。

    b)同样,整个二进制文件被拆分,匹配后没有上下文,尽管已经为每一行创建了一个上下文:B1B4的赋值创建了一个上下文,从B11B44的第二组作业也会创建一个上下文。因此,我们总共创建和使用了2个上下文。

  2.   

    根据文件[...]

    这部分对我来说也不是很清楚,但这是我能想到的。

    a)是的,在函数递归执行的整个持续时间内只会分配一个上下文。

    b)实际上没有提到区分尾递归与非尾递归。但是,给出的示例显然是一个可以转换为尾部递归的函数(虽然它并非无足轻重)。我认为当子句包含多个上下文路径时,编译器决定复制匹配的上下文。在这种情况下,编译器检测到该函数是尾部可优化的,并且不进行分配。

    c)我们看到在您复制的示例之后的示例中发生了相反的情况,其中包含一个案例表达式:在那里,上下文可能遵循2个不同的路径,因此编译器必须在每个递归级别强制分配

  3.   

    如果我通过尾递归传递一个大的二进制文件(比如1兆字节)[...]

    来自§4.1:

      

    子二进制文件由split_binary / 2创建,当二进制文件以二进制模式匹配时。子二进制是对另一个二进制文件(refc或堆二进制文件的一部分,从不进入另一个子二进制文件)的引用。因此,匹配二进制文件相对便宜,因为实际的二进制数据永远不会被复制。

    当处理二进制文件时,缓冲区用于存储实际数据,子部分的任何匹配都实现为包含指向原始缓冲区的指针的结构,加上偏移量和长度,指示哪个子部分正在考虑。这是文档中提到的子二进制类型。

  4. 我匹配哪个二进制文件 - 无论大小 - 都很重要......

    同样的§4.1:

      

    二进制容器称为refc二进制文件(引用计数二进制文件的缩写)和堆二进制文件。

         

    Refc二进制文件由两部分组成:存储在进程堆上的对象,称为ProcBin,二进制对象本身存储在所有进程堆之外。

    [...]

      

    堆二进制文件是小型二进制文件,最多64个字节,直接存储在进程堆上。当进程被垃圾收集并作为消息发送时,它们将被复制。它们不需要垃圾收集器进行任何特殊处理。

    这表明根据二进制文件的大小,它可以存储为进程外的大缓冲区,并通过代理结构在进程中引用,或者如果该二进制文件 64字节以下,它将直接存储在处理它的进程内存中。第一种情况是避免在共享它的进程在同一节点上运行时复制二进制文件。