【问题标题】:How are records stored in erlang, and how are they mutated?记录是如何存储在 erlang 中的,它们是如何变异的?
【发布时间】:2014-09-28 06:30:29
【问题描述】:

我最近遇到了一些类似于以下内容的代码:

-record(my_rec, {f0, f1, f2...... f711}).

update_field({f0, Val}, R) -> R#my_rec{f0 = Val};
update_field({f1, Val}, R) -> R#my_rec{f1 = Val};
update_field({f2, Val}, R) -> R#my_rec{f2 = Val};
....
update_field({f711, Val}, R) -> R#my_rec{f711 = Val}.

generate_record_from_proplist(Props)->
    lists:foldl(fun update_field/2, #my_rec{}, Props).

我的问题是关于记录实际发生的情况 - 假设记录有 711 个字段,我从 proplist 生成它 - 因为记录是不可变的,所以我们至少在语义上会生成一个新的完整记录foldr 中的每一步 - 使看起来像参数长度呈线性的函数变为长度实际上是二次的函数,因为每个插入的记录长度都有对应的更新 - 我是否正确在这个假设下,或者编译器是否足够智能 救我?

【问题讨论】:

标签: optimization erlang


【解决方案1】:

记录是元组,第一个元素包含记录的名称,下一个元素包含记录字段。

不存储字段的名称,它是编译器的工具,当然还有程序员的工具。我认为它的引入只是为了避免编写程序时出现字段顺序错误,并在发布新版本时允许元组扩展而不重写所有模式匹配。

您的代码将生成 713 个元素的元组的 712 个副本。

【讨论】:

  • 我给了你点帕斯卡 - 但我还是想知道,erlang vm 是否将记录存储在一个内存块中,或者是存储在树状结构中的元组,从而减少更新痛苦然后从头开始重建整个记录,如果它是第二个选项,代码虚拟机将能够重用大量引用。
  • 您可以在此处阅读有关内部表示的更多信息:erlang-factory.com/upload/presentations/467/… 看起来记录是连续的内存块。
  • 我一直在寻找这份文件,但@tkowal 比我快得多 :o)
【解决方案2】:

恐怕编译器不够聪明。 您可以在SO answer 中阅读更多内容。如果你有这么多的字段并且你想在 O(1) 时间内更新它,你应该使用ETS tables

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    相关资源
    最近更新 更多