我可以使用"空指针优化"对于我自己的非指针类型?

时间:2015-05-23 14:49:39

标签: optimization rust

当你有Option<&T>时,编译器知道NULL永远不是&Tencodes the None variant as NULL instead的可能值。这样可以节省空间:

use std::mem;

fn main() {
    assert_eq!(mem::size_of::<&u8>(), mem::size_of::<Option<&u8>>());
}

但是,如果使用非指针类型执行相同的操作,则无需额外的位来存储该值,并且需要额外的空间:

use std::mem;

fn main() {
    // fails because left is 1 and right is 2
    assert_eq!(mem::size_of::<u8>(), mem::size_of::<Option<u8>>()); 
}

一般来说,这是正确的。但是,我想选择加入优化,因为我知道我的类型有某些不可能的值。作为一个例子,我可能有一个有年龄的玩家角色。年龄可能未知,但永远不会高于255

struct Age(u8);

struct Player {
    age: Option<Age>,
}

我希望能够告知优化程序此约束 - Age永远不会是255,因此将该位模式用作{{1}是安全的}}。这可能吗?

1 个答案:

答案 0 :(得分:19)

从Rust 1.28开始,您可以使用implode()(和朋友)。这作为一个包装器,告诉编译器一个数字的内容将从不包含一个文字零。这也是Option<Box<T>>指针大小的原因。

以下是一个示例,说明如何创建Age并阅读其有效负载。

use std::num::NonZeroU8;

struct Age(NonZeroU8);

impl Age {
    pub fn new(age: u8) -> Age {
        let age = NonZeroU8::new(age).expect("Age cannot be zero!");
        Age(age)
    }

    pub fn age(&self) -> u8 {
        self.0.get()
    }
}

struct Player {
    age: Option<Age>,
}

fn main() {
    println!("size: {}", std::mem::size_of::<Player>());
    // Output: size: 1
}