rkyvRust 的零拷貝反序列化框架
rkyv 是一個用于 rust 的零拷貝反序列化框架。
它類似于其他零拷貝反序列化框架,例如 Cap'n Proto 和 FlatBuffers。然而,前者具有外部模式和嚴(yán)格限制的數(shù)據(jù)類型,而 rkyv 允許在代碼中定義所有序列化類型,并且可以序列化其他類型無法序列化的各種類型。此外,rkyv 被設(shè)計為幾乎沒有開銷,并且在大多數(shù)情況下將執(zhí)行與本機類型完全相同的操作。
與 serde 一樣,rkyv 使用 Rust 強大的特征系統(tǒng)來序列化數(shù)據(jù)而無需反射。盡管具有廣泛的功能,但你也只需為使用的功能付費。如果你的數(shù)據(jù)檢出,序列化過程可以像memcpy一樣簡單。與 serde 一樣,這允許 rkyv 以類似于手寫序列化程序的速度執(zhí)行。
與 serde 不同,rkyv 生成的數(shù)據(jù)保證沒有反序列化。如果你將數(shù)據(jù)寫入磁盤,你只需將文件mmap??????寫入內(nèi)存,投射一個指針,你的數(shù)據(jù)就可以使用了。這使其成為高性能和 IO 密集型應(yīng)用程序的理想選擇。
通過 Pin API 支持有限的數(shù)據(jù)突變,如果需要完整的突變功能,歸檔的值可以通過 Deserialize 真正反序列化。
rkyv 有一個 hashmap 實現(xiàn),它是為零拷貝反序列化而構(gòu)建的,所以你可以隨意序列化你的 hashmaps。該實現(xiàn)使用壓縮、散列和置換算法執(zhí)行完美散列,以使用盡可能少的內(nèi)存,同時仍然執(zhí)行快速查找。
它還帶有 B+ 樹實現(xiàn),該實現(xiàn)通過將數(shù)據(jù)拆分為易于分頁的 4KB 段來實現(xiàn)最佳性能。這使得它非常適合為批量數(shù)據(jù)構(gòu)建不可變的數(shù)據(jù)庫和結(jié)構(gòu)。
rkyv 還支持上下文序列化、反序列化和驗證。它可以正確地序列化和反序列化共享指針,如Rc和Arc,并且可以擴展以支持自定義上下文類型。
最后,rkyv 使得序列化 trait 對象成為可能,并且無需反序列化就可以將它們用作 trait 對象。更多細節(jié)見archive_dyn crate。
雖然 rkyv 是最終數(shù)據(jù)的一種很好的格式,但它缺乏完整的模式系統(tǒng),并且不能很好地進行數(shù)據(jù)遷移和模式升級。如果你的用例需要這些功能,可能需要額外的庫來在 rkyv 之上構(gòu)建這些功能??梢允褂门c rkyv 相同類型的其他序列化框架,如 serde,無沖突。
示例:
use rkyv::{Archive, Deserialize, Serialize}; // bytecheck can be used to validate your data if you want use bytecheck::CheckBytes; #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] // This will generate a PartialEq impl between our unarchived and archived types #[archive(compare(PartialEq))] // To use the safe API, you have to derive CheckBytes for the archived type #[archive_attr(derive(CheckBytes, Debug))] struct Test { int: u8, string: String, option: Option<Vec<i32>>, } let value = Test { int: 42, string: "hello world".to_string(), option: Some(vec![1, 2, 3, 4]), }; // Serializing is as easy as a single function call let bytes = rkyv::to_bytes::<_, 256>(&value).unwrap(); // Or you can customize your serialization for better performance // and compatibility with #![no_std] environments use rkyv::ser::{Serializer, serializers::AllocSerializer}; let mut serializer = AllocSerializer::<0>::default(); serializer.serialize_value(&value).unwrap(); let bytes = serializer.into_serializer().into_inner(); // You can use the safe API for fast zero-copy deserialization let archived = rkyv::check_archived_root::<Test>(&bytes[..]).unwrap(); assert_eq!(archived, &value); // Or you can use the unsafe API for maximum performance let archived = unsafe { rkyv::archived_root::<Test>(&bytes[..]) }; assert_eq!(archived, &value); // And you can always deserialize back to the original type let deserialized: Test = archived.deserialize(&mut rkyv::Infallible).unwrap(); assert_eq!(deserialized, value);
