Memory 如何在Rust的枚举中找到最大的变体?

Memory 如何在Rust的枚举中找到最大的变体?,memory,enums,rust,Memory,Enums,Rust,我正在努力提高rust程序的性能,这要求我减少一些大型enums的大小。比如说 枚举EE{ A、 //0 B(i32),//4 C(i64),//8 D(字符串),//24 E{//16 x:i64, y:i32, }, } fn main(){ println!(“{}”,std::mem::size_of::());//32 } 打印32。但是如果我想知道EE::A的大小,我会得到一个编译错误 错误[E0573]:应为类型,找到变量'EE::A` -->src/main.rs:14:40

我正在努力提高rust程序的性能,这要求我减少一些大型
enum
s的大小。比如说

枚举EE{ A、 //0 B(i32),//4 C(i64),//8 D(字符串),//24 E{//16 x:i64, y:i32, }, } fn main(){ println!(“{}”,std::mem::size_of::());//32 } 打印
32
。但是如果我想知道
EE::A
的大小,我会得到一个编译错误

错误[E0573]:应为类型,找到变量'EE::A`
-->src/main.rs:14:40
|
14 | println!(“{}”,std::mem::size_of::());
|                                        ^^^^^
|                                        |
|不是一种类型
|帮助:尝试使用变量的枚举:`crate::EE`
错误:由于上一个错误而中止
错误:无法编译“播放”。

有没有办法找出哪个变量占用的空间最大?

没有,没有办法只获得
枚举的一个变量的大小。您所能做的最好的事情就是获取变量所包含内容的大小,就像它是一个独立的结构一样:

    println!("sizeof EE::A: {}", std::mem::size_of::<()>());         // 0
    println!("sizeof EE::B: {}", std::mem::size_of::<i32>());        // 4
    println!("sizeof EE::C: {}", std::mem::size_of::<i64>());        // 8
    println!("sizeof EE::D: {}", std::mem::size_of::<String>());     // 24
    println!("sizeof EE::E: {}", std::mem::size_of::<(i64, i32)>()); // 16
println!(“sizeof EE::A:{}”,std::mem::size_of::());//0
普林顿!(“sizeof EE::B:{}”,std::mem::size_of::());//4.
普林顿!(“sizeof EE::C:{}”,std::mem::size_of::());//8.
普林顿!(“sizeof EE::D:{}”,std::mem::size_of::());//24
普林顿!(“sizeof EE::E:{}”,std::mem::size_of::());//16
甚至这也不是特别有用,因为它包括可能用于存储标记的填充字节;正如您所指出的,如果
D
缩小到一个指针,则
enum
的大小可以减少到16,但仅从大小上看,您无法知道这一点。如果将
y
定义为
i64
,则每个变量的大小将相同,但
enum
的大小需要为24。对齐是另一个混淆因素,它使得
枚举的大小比“最大变量加上标记的大小”更复杂

当然,这都是高度依赖于平台的,您的代码不应该依赖任何具有特定布局的
enum
(除非您可以用
#[repr]
注释来保证)


如果您担心某个特定的
enum
,那么获取每个包含类型的大小并不困难。Clippy还有一个用于
enum
s的lint,变量之间的尺寸差异极大。但是,我不建议仅使用大小来对
enum
布局进行手动优化,也不建议将大小仅为几个指针的东西装箱——间接抑制编译器可能能够执行的其他类型的优化。如果您优先考虑最小的空间使用,您可能会意外地使代码在此过程中慢得多。

“是否有一种有效的方法来获取每个枚举变量的大小?”→ 所有变量都有相同的大小,即对应枚举的大小。@mcarton“所有变量都有相同的大小”,这取决于占用最多内存的变量的大小,如果我能快速找到该变量,我可以快速改进枚举定义。我想问一下如何快速找到该变量,很抱歉,我表达得不好。@mcarton在上面的例子中,
D(String)
需要的内存大小最多,是24,所以枚举的大小是(24+8)=32。如果我用
D(String)
替换
D(Box)
,枚举的大小可以减少到16。如果rust能告诉我
D(String)
使用24字节,这是一个很大的好处,这是所有变量中最大的一个,因此枚举大小应该是32字节,如果
D(String)
的大小可以减小,枚举的大小也可以减小。@mcarton虽然您在技术上是正确的,但我认为您在吹毛求疵,很清楚OP的意图。甚至还有一个Clippy lint表示“枚举上变量之间的大大小差异”,因为有一个枚举大小和每个变量的空间利用率的概念。在类似示例的情况下,您也可以使用
Box
,它与
Box
基本相同,但只需要16字节,因此,整个枚举可以容纳24个,同时避免了双重间接寻址的成本。很少有好的理由使用