如何在Rust的枚举中找到最大的变体? [英] How to find biggest variant in an enum in Rust?

查看:39
本文介绍了如何在Rust的枚举中找到最大的变体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试提高rust程序的性能,这要求我减小一些大型 enum 的大小.例如

 枚举EE {A,//0B(i32),//4C(i64),//8D(String),//24E {//16x:i64,y:i32,},}fn main(){println!("{}",std :: mem :: size_of ::< EE>());//32} 

打印 32 .但是,如果我想知道 EE :: A 的大小,则会出现编译错误

 错误[E0573]:预期类型,找到了变体"EE :: A"->src/main.rs:14:40|14 |println!("{}",std :: mem :: size_of ::< EE :: A>());|^^^^^|||不是类型|帮助:尝试使用变体的枚举:crate :: EE错误:由于先前的错误而中止错误:无法编译`play_rust`. 

是否有办法找出哪个变体占用最多的空间?

解决方案

不,无法获得 enum 的一个变体的大小.最好的办法就是获取变体包含的内容的大小,就好像它是一个独立的结构一样:

  println!("sizeof EE :: A:{}",std :: mem :: size_of ::<()>());//0println!("sizeof EE :: B:{}",std :: mem :: size_of ::< i32>());//4println!("sizeof EE :: C:{}",std :: mem :: size_of ::< i64>());//8println!("sizeof EE :: D:{}",std :: mem :: size_of ::< String>());//24println!("sizeof EE :: E:{}",std :: mem :: size_of ::<(i64,i32)>());//16 

这并不是特别有用,因为它包括可用于存储标签的填充字节.如您所指出的,如果将 D 缩小为单个指针,则可以将 enum 的大小减小为16,但是仅通过查看大小.如果将 y 定义为 i64 ,则每个变体的大小将相同,但是 enum 的大小将为24.对齐是另一个令人困惑的因素,它使 enum 的大小比最大变体的大小加标签的大小"更复杂.

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

如果您担心某个特定的 enum ,则获取每个包含的类型的大小并不难.Clippy还具有 enum 的皮棉,变体之间的尺寸差异非常大.但是,我不建议单独使用size来对 enum 布局进行手动优化,或装箱大小只是几个指针的东西-间接抑制编译器可能进行的其他类型的优化做.如果您优先考虑最小化空间的使用,则可能会意外地使您的代码在此过程中变慢.

I'm trying to improve the performance of a rust program, which requires me to reduce the size of some large enums. For example

enum EE {
    A, // 0
    B(i32), //4
    C(i64), // 8
    D(String), // 24
    E { // 16
        x: i64,
        y: i32,
    },
}

fn main() {
    println!("{}", std::mem::size_of::<EE>()); // 32
}

prints 32. But if I want to know the size of EE::A, I get a compile error

error[E0573]: expected type, found variant `EE::A`
  --> src/main.rs:14:40
   |
14 |     println!("{}", std::mem::size_of::<EE::A>());
   |                                        ^^^^^
   |                                        |
   |                                        not a type
   |                                        help: try using the variant's enum: `crate::EE`

error: aborting due to previous error

error: could not compile `play_rust`.

Is there a way to find out which variant takes the most space?

解决方案

No, there is no way to get the size of just one variant of an enum. The best you can do is get the size of what the variant contains, as if it were a standalone struct:

    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

Even this isn't especially useful because it includes padding bytes that may be used to store the tag; as you point out, the size of the enum can be reduced to 16 if D is shrunk to a single pointer, but you can't know that from looking at just the sizes. If y were instead defined as i64, the size of each variant would be the same, but the size of the enum would need to be 24. Alignment is another confounding factor that makes the size of an enum more complex than just "the size of the largest variant plus the tag".

Of course, this is all highly platform-dependent, and your code should not rely on any enum having a particular layout (unless you can guarantee it with a #[repr] annotation).

If you have a particular enum you're worried about, it's not difficult to get the size of each contained type. Clippy also has a lint for enums with extreme size differences between variants. However, I don't recommend using size alone to make manual optimizations to enum layouts, or boxing things that are only a few pointers in size -- indirection suppresses other kinds of optimizations the compiler may be able to do. If you prioritize minimal space usage you may accidentally make your code much slower in the process.

这篇关于如何在Rust的枚举中找到最大的变体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆