【问题标题】:What is the preferable memory layout of Algebraic Data Types?代数数据类型的首选内存布局是什么?
【发布时间】:2016-09-21 21:58:16
【问题描述】:

代数数据类型 (ADT) 是由可能递归的单位、乘积和总和类型组成的类型。

考虑一下 Haskell 中的一个简单 ADT:

data Tree = Empty
          | Leaf Int
          | Node Tree Tree

或者 Rust 中的另一个例子:

enum Message {
    Quit,
    ChangeColor(i32, i32, i32),
    Move { x: i32, y: i32 },
    Write(String),
}

Haskell(垃圾回收)和 Rust(非垃圾回收)实际上是如何在内存中表示这些的,它们应该如何表示?

我主要对更简单的非垃圾回收案例感兴趣,但如果非垃圾回收,解决方案必须对堆和堆栈都适用,例如 Rust。

LLVM 或 C/C++ 中的表示是我感兴趣的。

使用第二个例子,我可以想到两个选择:

选项 1,使用联合:

enum MCtor { CQ, CCC, CM, CW  };

struct Message {
    enum MCtor ctor;
    union {
        void*; /* Quit */
        struct { int r; int g; int b; } /* ChangeColor */
        struct { int x; int y; } /* Move */
        struct { char* str; } /* Write */
    };
};

选项 2,使用单独分配,void* 和(位)转换:

enum MCtor { CQ, CCC, CM, CW  };

typedef struct { int r; int g; int b; } ChangeColor;
typedef struct { int x; int y; } Move;
typedef struct { char* str; } Write;

struct Message {
    enum MCtor ctor;
    void* data;
};

模式匹配只是switchmsg -> ctor 的问题。

哪一个更可取,尤其是考虑到递归类型?

在我的脑海中,我猜第一个的局部性更好,它可以避免负载,虽然它可能会使用更多的内存......所以第二个选项有更好的内存占用但性能更差.. .?

【问题讨论】:

  • 这可能会因为太宽泛而被关闭。您在问哪个实现细节是最好的,但是变量太多了。您的目标是什么机器架构(缓存对齐和填充肯定会发挥作用)?您是否尝试优化速度或内存使用?我希望它还取决于将存储什么样的东西。您的语言中的所有内容都表示为指针吗?
  • 请注意,Rust 直接允许递归类型定义。如果是这样,结构的大小将是无限的。它要求您通过引用或堆分配的存储添加一个间接层。
  • 没有语言 C/C++。不确定 C++ 是否允许匿名 struct/union 成员。而且您的问题主要是基于意见的并且过于广泛(选择一个)。任何都是有效的关闭理由。
  • @Olaf 我读到他们确实不允许在 c++ 中使用。
  • @Centril:ADT 不是元组,但它是一个联合:它是 一个 empy、leaf 或 node,而不是“全部”。只有节点是元组。

标签: llvm algebraic-data-types


【解决方案1】:

以下是一些解释 GHC 如何实现数据结构的资源:

【讨论】:

  • 很好,rustc 是如何做到的?
  • 现在让我成为一名 Rust 专家 :-)
  • 我意识到,如果你返回,第二个选项实际上是不可能在堆栈上使用的,因为那样堆栈分配的数据字段将被释放...... Rust 像第一个选项一样为最大的变体分配在我的问题中,使用以下方法演示:gist.github.com/anonymous/7cc0c81c888d4c61d952512fea05667a 产生%Message = type { i8, [7 x i8], [4 x i64] }
猜你喜欢
  • 2019-06-09
  • 2017-12-12
  • 2012-04-01
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多