dtolnay / erased-serde

Type-erased Serialize, Serializer and Deserializer traits
Apache License 2.0
709 stars 36 forks source link

Deeply nested structs consume quadratic stack space #61

Open dtolnay opened 2 years ago

dtolnay commented 2 years ago
use serde::Serialize;

#[derive(Serialize)]
struct Node {
    k: Option<Box<dyn erased_serde::Serialize>>,
}

fn main() {
    std::thread::Builder::new()
        .stack_size(2 * 1024 * 1024)
        .name("test".to_string())
        .spawn(move || {
            let mut node = None::<Box<dyn erased_serde::Serialize>>;
            for _ in 0..100 {
                node = Some(Box::new(Node { k: node }));
            }
            let json = serde_json::to_string(&node).unwrap();
            println!("{json}");
        })
        .unwrap()
        .join()
        .unwrap();
}

Backtrace according to gdb

dtolnay commented 2 years ago

Cleaner backtrace

use serde::Serialize;

#[derive(Serialize)]
struct Node<'a> {
    k: &'a dyn erased_serde::Serialize,
}

fn main() {
    std::thread::Builder::new()
        .stack_size(2 * 1024 * 1024)
        .name("test".to_string())
        .spawn(move || {
            let mut node = Node { k: &() };
            for _ in 0..100 {
                node = Node { k: Box::leak(Box::new(node)) };
            }
            let json = serde_json::to_string(&node).unwrap();
            println!("{json}");
        })
        .unwrap()
        .join()
        .unwrap();
}