Why does Serde not support Rc and Arc types by default?

左心房为你撑大大i 提交于 2020-03-22 08:26:27

问题


Please explain the Serde rc feature

Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types does not preserve identity and may result in multiple copies of the same data. Be sure that this is what you want before enabling this feature.

Serializing a data structure containing reference-counted pointers will serialize a copy of the inner value of the pointer each time a pointer is referenced within the data structure. Serialization will not attempt to deduplicate these repeated data.

Deserializing a data structure containing reference-counted pointers will not attempt to deduplicate references to the same data. Every deserialized pointer will end up with a strong count of 1.

Why does this feature flag exist and why isn't it default behaviour? What does it mean by

Serializing and deserializing these types does not preserve identity and may result in multiple copies of the same data

I know that it is related to Serde issue 194. The last message of the issue says

If you want to make sure you don't accidentally end up with a derived impl containing an rc, open a clippy issue.

Does the feature flag exist to catch unexpected usages of an Rc struct?


回答1:


As stated in Serde issue 194, the drawbacks of the implementation of deserializing to Rc or Arc are:

  • Potentially increased memory usage
  • Equality comparison that relies on comparison of address breaks
  • Interior mutability is not reflected in copies

This is echoed in the feature flag documentation:

Serialization will not attempt to deduplicate these repeated data.

Deserializing a data structure containing reference-counted pointers will not attempt to deduplicate references to the same data.

The usual point of an Rc or Arc is to share data. This sharing doesn't happen when deserializing to a struct containing Rc or Arc. In this example, 5 completely distinct Rc<str>s are created with no relation to each other, even though they all have the same content:

use std::{rc::Rc, ptr};

fn main() {
    let json = r#"[
        "alpha",
        "alpha",
        "alpha",
        "alpha",
        "alpha"
    ]"#;

    let strings = serde_json::from_str::<Vec<Rc<str>>>(json).unwrap();

    dbg!(ptr::eq(strings[0].as_ref(), strings[1].as_ref()));
}
[src/main.rs:14] ptr::eq(strings[0].as_ref(), strings[1].as_ref()) = false

This is especially bad when you have an Rc<RefCell<_>> or other type with interior mutability, as you might expect that modifying one of the items modifies all of the items.

See also:

  • Is there a way to distingush between different `Rc`s of the same value?
  • How can I get Serde to allocate strings from an arena during deserialization?


来源:https://stackoverflow.com/questions/60604346/why-does-serde-not-support-rc-and-arc-types-by-default

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!