[Rust] zerocopy

zerocopy๋Š” ๋ณต์‚ฌ๋น„์šฉ ์—†๋Š” ๋ฉ”๋ชจ๋ฆฌ ์กฐ์ž‘์„ ๊ฐ„ํŽธํ•œ ํ˜•ํƒœ๋กœ ๋ณด์กฐํ•˜๋Š” crate๋‹ค.

๊ตฌ๊ธ€์ด ํ‘ธํฌ์‹œ์•„ ์ œ์ž‘์— ์“ฐ๋ ค๊ณ  ๋งŒ๋“ ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ๋‹ค.



์™œ ํ•„์š”ํ•œ๊ฐ€?

zero-copy ๋ฐฉ๋ฒ•๋ก ์— ๋Œ€ํ•œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋Š” ๋ณ„๋„ ํฌ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
https://blog.naver.com/sssang97/223629674161

์•„๋ฌดํŠผ๊ฐ„์— ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋“ค๊ณ ์˜จ ๋ฐ”์ดํŠธ์—ด ๋ฐ์ดํ„ฐ๋ฅผ Rust์—์„œ ์ œ๋Œ€๋กœ ๋‹ค๋ฃจ๋ ค๋ฉด ์—ญ์ง๋ ฌํ™”/์ง๋ ฌํ™”๋ฅผ ๊ฑฐ์ณ์„œ struct/enum์„ ํ†ตํ•ด ๊ฐ€๊ณตํ•˜๋Š”๊ฒŒ ์ฃผ๋œ ์‚ฌ์šฉ ํŒจํ„ด์ผ ๊ฒƒ์ด๋‹ค.

๊ทผ๋ฐ ๊ทธ๋ƒฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์„œ ์ง๋ ฌํ™”์™€ ์—ญ์ง๋ ฌํ™”๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉด ํ•„์‹œ ๋ถˆํ•„์š”ํ•œ ๋ณต์‚ฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค.

์ด crate๋Š” ๋ณต์‚ฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ํ˜•ํƒœ์˜ unsafe ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ๊ฐ์‹ธ์„œ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋‹ค.
์ด๊ฒƒ ์ž์ฒด๋กœ syscall๋“ค์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋ณด์กฐ์ ์ธ ์šฉ๋„๋‹ค.




๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

์šฐ์„  zerocopy ์ข…์†์„ฑ์„ ์ ์ ˆํžˆ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

derive๋Š” features๋กœ ๋„ฃ๋Š” ๋Œ€์‹ ์— zerocopy-derive๋ฅผ ๋”ฐ๋กœ ๋„ฃ์„ ์ˆ˜๋„ ์žˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด ์ปดํŒŒ์ผ ์†๋„๊ฐ€ ๋‚˜์•„์ง„๋‹ค๋‚˜...

์•„๋ฌดํŠผ, zerocopy๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ณดํ†ต ์ด๋Ÿฐ ๋А๋‚Œ์œผ๋กœ ๊ตฌ์กฐ์ฒด๋ฅผ ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

์‹ค์งˆ์ ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ํŠธ๋ ˆ์ž‡์€ ์ด 4๊ฐ€์ง€๋‹ค.

TryFromBytes/FromBytes๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์•Œ๊ณ ์žˆ๋Š” TryFrom ํŒจํ„ด์œผ๋กœ ๋ฐ”์ดํŠธ์—ด์„ ๊ตฌ์กฐ์ฒด ๋“ฑ์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ๋ฐ˜ํ™˜ ํƒ€์ž…์€ Result<&T, Err>๋‹ค.
owned๊ฐ€ ์•„๋‹Œ ์ฐธ์กฐํ˜•์œผ๋กœ ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์‚ฌ ๋™์ž‘์„ ์ตœ์†Œํ™”ํ•œ ์ฑ„๋กœ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

IntoBytes๋Š” ๊ฐ„๋‹จํ•˜๋‹ค. ๊ตฌ์กฐ์ฒด ๋“ฑ์„ ๋ฐ”์ดํŠธ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

FromZeros๋Š” ์ข€ ํŠน์ดํ•œ๋ฐ, ๊ฐ์ฒด๊ฐ€ ๊ธฐ๋ณธ๊ฐ’(0)์ธ ์ƒํƒœ๊ฐ€ ์œ ํšจํ•œ ์ƒํƒœ์ž„์„ ๋ณด์žฅํ•˜๋Š” trait์ด๋‹ค.

๋˜ zero-copy์—๋Š” zerocopy ๊ตฌํ˜„์— ํ•„์š”ํ•œ ๋ณด์žฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋งˆ์ปค trait์ด 3๊ฐ€์ง€ ์žˆ๋‹ค. ์•„๋ž˜ ๋งˆ์ปค๋“ค์„ ์ ์ ˆํžˆ ๋‹ฌ์•„์ค˜์•ผ ์œ„์˜ ๊ธฐ๋Šฅ derive๋„ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

KnownLayout๋Š” ๋Œ€๋ถ€๋ถ„์˜ zerocopy ์‚ฌ์šฉ์‚ฌ๋ก€์— ํ•„์š”ํ•œ ๊ธฐ๋ณธ ๋งˆ์ปค๋‹ค. ์ด๊ฑธ ๋‹ฌ์•„๋†”์•ผ ์‹ค์ œ ๊ตฌ์กฐ์ฒด์˜ ๋ ˆ์ด์•„์›ƒ ๋ถ„์„์„ ๊ตฌํ˜„ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
Immutable๋Š” ํ•ด๋‹น ํƒ€์ž…์ด ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•ด์•ผํ•จ์„ ๋œปํ•œ๋‹ค.
Unaligned๋Š” ๋ฉ”๋ชจ๋ฆฌ alignment๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋Š” ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.


์ผ๋‹จ ํ•œ๋ฒˆ ์‹ค์ œ๋กœ ๋งŒ๋“ค์–ด๋ณด์ž.

use zerocopy::*;

#[derive(Debug, KnownLayout, Immutable, TryFromBytes)]
#[repr(u32)]
enum Cuppa {
    Tea { iced: bool, milk: u8 } = u32::from_ne_bytes(*b"CHAI"),
    Coco { marshmallows: u8 } = u32::from_ne_bytes(*b"COCO"),
}

๊ตฌ์กฐ์ฒด ํ•˜๋‚˜๋ฅผ zerocopy๋ฅผ ๋•์ง€๋•์ง€ ๋‹ฌ๋ฉด์„œ ๋งŒ๋“ค์—ˆ๋‹ค.
enum์— ๊ฐ’์„ ํ• ๋‹นํ•œ๊ฑด ๋ณ„ ์˜๋ฏธ๋Š” ์—†๋‹ค. ๊ทธ๋ƒฅ ํ•œ๊ฑฐ๊ณ , ๊ผญ ์ €๋ž˜์•ผ ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

์ด ๊ฒฝ์šฐ์—” TryFromBytes๋ฅผ ๋‹ฌ์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”์ดํŠธ์—ด->๊ตฌ์กฐ์ฒด ๋ณ€ํ™˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿผ ์ด๋Ÿฐ ๋А๋‚Œ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    let data = u64::from_ne_bytes([b'C', b'H', b'A', b'I', 1, 42, 0, 0]);

    let obj = Cuppa::try_ref_from_bytes(data.as_bytes());

    if let Ok(Cuppa::Tea { iced, milk }) = obj {
        println!("iced: {}, milk: {}", iced, milk);
    }

๋ฐ”์ดํŠธ์—ด์„ ๋ฐ›์•„์„œ, ๊ทธ๊ฑธ ๋ณ€ํ™˜ํ•˜๊ณ  ์ถœ๋ ฅํ•˜๋„๋ก ํ–ˆ๋‹ค.


๊ทธ๋Ÿผ ์ž˜ ๋™์ž‘ํ•  ๊ฒƒ์ด๋‹ค.

์•ž์„œ ๋งํ–ˆ๋“ฏ์ด ์ €๊ธฐ์„œ ์ƒ์„ฑ๋œ obj ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋œ ์ฑ„๋กœ ๊ตฌ์กฐ์ฒด ๋ชจ์–‘์„ ๊ฐ–์ถ˜ ๊ฒƒ์ผ ๋ฟ์ด๋‹ค.
๊ทธ๋ž˜์„œ ์‹ค์ œ๋กœ๋Š” ๋ณต์‚ฌ๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ฐธ์กฐ๋œ ๊ฒƒ์ด๋‹ค.

์ด๊ฑฐ ๋ง๊ณ ๋„ ๋ฐ”์ดํŠธ์—ด ์—ญ๋ณ€ํ™˜์ด๋‚˜ ์ž์ž˜ํ•œ ๋ณด์กฐ๊ธฐ๋Šฅ๋“ค์ด ์žˆ๊ธด ํ•˜์ง€๋งŒ, ์ด๊ฒŒ zero-copy๋ผ๋Š” crate์˜ ํ•ต์‹ฌ์ด๋‹ค.



https://github.com/google/zerocopy/discussions/1680
https://google.github.io/comprehensive-rust/ko/bare-metal/useful-crates/zerocopy.html
https://github.com/google/zerocopy/discussions/1680