use std::{hint::black_box, rc::Rc};
use deepclone::DeepClone;
#[derive(Clone, DeepClone)]
struct Flat {
name: String,
values: Vec<u64>,
}
#[derive(Clone, DeepClone)]
struct Node {
value: u64,
children: Vec<Rc<Node>>,
}
fn chain(depth: u64) -> Node {
let mut node = Node {
value: 0,
children: Vec::new(),
};
for value in 1..depth {
node = Node {
value,
children: vec![Rc::new(node)],
};
}
node
}
fn dag(width: u64, shared_depth: u64) -> Node {
let shared = Rc::new(chain(shared_depth));
Node {
value: 0,
children: (0..width)
.map(|value| {
Rc::new(Node {
value,
children: vec![Rc::clone(&shared)],
})
})
.collect(),
}
}
fn main() {
divan::main();
}
fn naive(node: &Node) -> Node {
Node {
value: node.value,
children: node
.children
.iter()
.map(|child| Rc::new(naive(child)))
.collect(),
}
}
#[divan::bench_group(name = "flat, no shared pointers")]
mod flat {
use deepclone::DeepClone;
use super::{Flat, black_box};
#[divan::bench]
fn clone(bencher: divan::Bencher) {
let source = input();
bencher.bench_local(|| black_box(black_box(&source).clone()));
}
#[divan::bench]
fn deep_clone(bencher: divan::Bencher) {
let source = input();
bencher.bench_local(|| black_box(black_box(&source).deep_clone()));
}
fn input() -> Flat {
Flat {
name: "solver".to_owned(),
values: (0..1024).collect(),
}
}
}
#[divan::bench_group(name = "dag, 16 nodes sharing a 64-node subtree")]
mod shared {
use deepclone::DeepClone;
use super::{black_box, dag, naive};
#[divan::bench]
fn clone(bencher: divan::Bencher) {
let source = dag(16, 64);
bencher.bench_local(|| black_box(black_box(&source).clone()));
}
#[divan::bench]
fn deep_clone(bencher: divan::Bencher) {
let source = dag(16, 64);
bencher.bench_local(|| black_box(black_box(&source).deep_clone()));
}
#[divan::bench]
fn naive_deep_clone(bencher: divan::Bencher) {
let source = dag(16, 64);
bencher.bench_local(|| black_box(naive(black_box(&source))));
}
}
#[divan::bench_group(name = "chain, 256 unique nodes")]
mod unshared {
use deepclone::DeepClone;
use super::{black_box, chain, naive};
#[divan::bench]
fn clone(bencher: divan::Bencher) {
let source = chain(256);
bencher.bench_local(|| black_box(black_box(&source).clone()));
}
#[divan::bench]
fn deep_clone(bencher: divan::Bencher) {
let source = chain(256);
bencher.bench_local(|| black_box(black_box(&source).deep_clone()));
}
#[divan::bench]
fn naive_deep_clone(bencher: divan::Bencher) {
let source = chain(256);
bencher.bench_local(|| black_box(naive(black_box(&source))));
}
}