reuse placeholder and empty nodes on each thread to reduce allocation (#2217)

This commit is contained in:
Evan Almloff authored and GitHub committed 2024-04-02 10:52:16 -07:00
1 parent 5df333fca2
commit c8140c78b3
1 file changed
+28 -6
+28 -6
View File
@@ -167,8 +167,14 @@ impl VNode {
/// Create a template with no nodes that will be skipped over during diffing /// Create a template with no nodes that will be skipped over during diffing
pub fn empty() -> Element { pub fn empty() -> Element {
Some(Self { use std::cell::OnceCell;
vnode: Rc::new(VNodeInner { // We can reuse all placeholders across the same thread to save memory
thread_local! {
static EMPTY_VNODE: OnceCell<Rc<VNodeInner>> = const { OnceCell::new() };
}
let vnode = EMPTY_VNODE.with(|cell| {
cell.get_or_init(move || {
Rc::new(VNodeInner {
key: None, key: None,
dynamic_nodes: Box::new([]), dynamic_nodes: Box::new([]),
dynamic_attrs: Box::new([]), dynamic_attrs: Box::new([]),
@@ -178,15 +184,26 @@ impl VNode {
node_paths: &[], node_paths: &[],
attr_paths: &[], attr_paths: &[],
}), }),
}), })
})
.clone()
});
Some(Self {
vnode,
mount: Default::default(), mount: Default::default(),
}) })
} }
/// Create a template with a single placeholder node /// Create a template with a single placeholder node
pub fn placeholder() -> Self { pub fn placeholder() -> Self {
Self { use std::cell::OnceCell;
vnode: Rc::new(VNodeInner { // We can reuse all placeholders across the same thread to save memory
thread_local! {
static PLACEHOLDER_VNODE: OnceCell<Rc<VNodeInner>> = const { OnceCell::new() };
}
let vnode = PLACEHOLDER_VNODE.with(|cell| {
cell.get_or_init(move || {
Rc::new(VNodeInner {
key: None, key: None,
dynamic_nodes: Box::new([DynamicNode::Placeholder(Default::default())]), dynamic_nodes: Box::new([DynamicNode::Placeholder(Default::default())]),
dynamic_attrs: Box::new([]), dynamic_attrs: Box::new([]),
@@ -196,7 +213,12 @@ impl VNode {
node_paths: &[&[]], node_paths: &[&[]],
attr_paths: &[], attr_paths: &[],
}), }),
}), })
})
.clone()
});
Self {
vnode,
mount: Default::default(), mount: Default::default(),
} }
} }