【问题标题】:What is the null pointer optimization in Rust?Rust 中的空指针优化是什么?
【发布时间】:2018-03-15 10:03:29
【问题描述】:

Learning Rust With Entirely Too Many Linked Lists,作者提到:

但是,如果我们有一种特殊的枚举:

enum Foo {
    A,
    B(ContainsANonNullPtr),
}

空指针优化开始,消除了标记所需的空间。如果变体是A,则整个枚举设置为所有0。否则,变体为B。这是可行的,因为B 永远不可能全部是0,因为它包含一个非零指针。

我猜作者是这么说的(假设A是4位,B是4位)

let test = Foo::A

内存布局是

0000 0000

但是

let test = Foo::B

内存布局是

some 8 bit non 0 value

这里究竟优化了什么?不都是8位的表示作者声称的时候是什么意思

这意味着&&mutBoxRcArcVec 以及 Rust 中的其他几个重要类型在放入 Option 时没有开销

【问题讨论】:

    标签: rust


    【解决方案1】:

    空指针优化基本上意味着如果您有一个包含两个变体的枚举,其中一个变体没有关联数据,而另一个变体具有关联数据,其中全零的位模式不是有效值,那么enum 本身将占用与关联值完全相同的空间量,使用全零位模式表示它是另一个变体。

    换句话说,这意味着Option<&T> 的大小与&T 完全相同,而不需要额外的单词。

    【讨论】:

    • 我明白这一点。但是编译器如何知道全零是否是无效值?我假设优化只适用于特定的内置类型。如果有,是哪些?
    • 编译器内置了各种类型的内存布局知识。例如,它知道&-references 永远不能为空。它还知道StringVec 永远不能全为零;在此之后进入实现,StringVec 支持,RawVecUnique 支持,Unique 包含*const T,但具有声明它可以的编译器属性t 为空。类似地,有一个 stdlib NonNull<T> 类型,其行为类似于永远不能为空的 *mut T
    • 详细说明,空字符串和向量不指向空值,它们指向一个容量为零的固定非空地址。其他容器也一样,比如可以廉价创建的 HashMaps。 Rust 标准库非常努力地避免指针中的空值,因此可以为空指针优化之类的事情保留全零值。
    【解决方案2】:

    enum 是一个标记的联合。没有优化它看起来像

    Foo::A;    // tag 0x00 data 0xXX
    Foo::B(2); // tag 0x01 data 0x02
    

    空指针优化去掉了单独的标签字段。

    Foo::A;    // tag+data 0x00
    Foo::B(2); // tag+data 0x02
    

    【讨论】:

    • 第二个例子似乎有点不准确,考虑到0x00 是整数的有效位模式,因此Foo::AFoo::B(0) 的含义不明确。跨度>
    【解决方案3】:

    我也学了太多链表,或许这段代码sn-p可以加深你的理解

    pub enum WithNullPtrOptimization{
        A,
        B(String),
    }
    
    pub enum WithoutNullPtrOptimization{
        A,
        B(u32),
    }
    
    fn main()  {
        println!("{} {}", std::mem::size_of::<WithNullPtrOptimization>(), std::mem::size_of::<String>()); // 24 24
        println!("{} {}", std::mem::size_of::<WithoutNullPtrOptimization>(), std::mem::size_of::<u32>()); // 8 4
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-19
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 2021-05-08
      • 2021-08-18
      • 2020-11-16
      相关资源
      最近更新 更多