Rust의 enum에 크기가 다른 형태를 열거하면 메모리 사이즈 효율이 나쁘다는 이야기
7581 단어 Rust
enum
를 정의했을 경우, 그 사이즈는 16 바이트가 됩니다.enum Hoge {
Char(i8),
Short(i16),
Long(i32),
LongLong(i64),
}
let size = mem::size_of::<Hoge>();
assert_eq!(size, 16);
Hoge
의 데이터 구조가 무엇인지 확인합니다.let long = Hoge::Long(65536);
let slice = unsafe { mem::transmute::<Hoge, [u8; 16]>(long) };
slice.iter()
.enumerate()
.for_each(|(i, v)| println!("index: {}, value: {:x}", i, v));
$ cargo run
index: 0, value: 2 // tag enum の何番目の識別子か
index: 1, value: 44 // _padding0 ここから
index: 2, value: ed // ↓
index: 3, value: 3 // ここまで
index: 4, value: 0 // data ここから
index: 5, value: 0 // ↓
index: 6, value: 1 // ↓
index: 7, value: 0 // ここまで
index: 8, value: 0 // _padding1 ここから
index: 9, value: 0 // ↓
index: 10, value: 0 // ↓
index: 11, value: 0 // ↓
index: 12, value: 0 // ↓
index: 13, value: 0 // ↓
index: 14, value: 0 // ↓
index: 15, value: 0 // ここまで
즉
enum Hoge
열거자의 데이터 구조를 가상적인 구조체로서 나타내면,struct EnumHoge {
tag: u8,
_padding0: [u8; ?],
data: i8 | i16 | i32 | i64,
_padding1: [u8; ?],
}
같은 느낌이 되고 있습니다.
_padding0
의 크기는 data
가 메모리 정렬 경계를 넘지 않도록 data
의 크기에 따라 달라집니다. Char
의 _padding
는 0. Short
는 1. Long
는 3. LongLong
그렇다면 7입니다. _padding1
에 16바이트의 나머지가 채워집니다.여기서 새로운 의문이. 만약 열거자의 수가 256 를 넘으면 어떻게 되는 것인가? 즉
tag
의 u8
가 오버플로우 하면 어떻게 되는 것인가? (현실적으로는 우선 있을 수 없다고 생각합니다만)실제로 해봤다.
enum Piyo {
LongLong0(i64),
LongLong1(i64),
LongLong2(i64),
LongLong3(i64),
// 省略
LongLong65534(i64),
LongLong65535(i64),
Char(i8),
Short(i16),
Long(i32),
}
VSCode에서 ↑를 쓰면 메모리가 끊어지고 스왑이 4GiB 이상으로 PC가 고정되었습니다.
어쩌면
tag
의 크기가 u32
로 바뀔 것입니다.이야기가 조금 탈선했습니다. 메모리 크기 효율이 나쁘다는 이야기로 되돌리자.
예를 들어 ↓ 이런 식으로
Hoge
를 Vec
에 넣으면 실제 데이터로서의 크기는 15바이트인데 padding 이 있기 때문에 64바이트도 사용해 버린다는 것입니다.enum Hoge {
Char(i8), // 1 バイト
Short(i16), // 2 バイト
Long(i32), // 4 バイト
LongLong(i64), // 8 バイト
}
// 1 + 2 + 4 + 8 = 15 バイト!
use Hoge::*;
let v = vec![Char(0), Short(1), Long(2), LongLong(3)];
// v の大きさは 16 * 4 = 64 バイト!
끝.
Reference
이 문제에 관하여(Rust의 enum에 크기가 다른 형태를 열거하면 메모리 사이즈 효율이 나쁘다는 이야기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/benki/items/32249f108a340c1c9b4a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)