improve performance

This commit is contained in:
Evan Almloff committed 2023-02-01 20:45:11 -06:00
1 parent 71a0bdf71d
commit d67b21c0e9
4 files changed
+45 -63

No files matched your search

+2 -2
View File
@@ -10,12 +10,12 @@ use crate::{
#[derive(Debug)] #[derive(Debug)]
pub struct NodeView<'a, V: FromAnyValue = ()> { pub struct NodeView<'a, V: FromAnyValue = ()> {
inner: &'a NodeData<V>, inner: &'a NodeData<V>,
mask: NodeMask, mask: &'a NodeMask,
} }
impl<'a, V: FromAnyValue> NodeView<'a, V> { impl<'a, V: FromAnyValue> NodeView<'a, V> {
/// Create a new NodeView from a VNode, and mask. /// Create a new NodeView from a VNode, and mask.
pub fn new(node: &'a NodeData<V>, view: NodeMask) -> Self { pub fn new(node: &'a NodeData<V>, view: &'a NodeMask) -> Self {
Self { Self {
inner: node, inner: node,
mask: view, mask: view,
+40 -58
View File
@@ -1,7 +1,7 @@
use anymap::AnyMap; use anymap::AnyMap;
use core::panic; use core::panic;
use parking_lot::RwLock; use parking_lot::RwLock;
use rustc_hash::FxHashSet; use rustc_hash::{FxHashMap, FxHashSet};
use std::any::{Any, TypeId}; use std::any::{Any, TypeId};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -11,7 +11,7 @@ use crate::node::{FromAnyValue, NodeData};
use crate::node_ref::{NodeMaskBuilder, NodeView}; use crate::node_ref::{NodeMaskBuilder, NodeView};
use crate::real_dom::RealDom; use crate::real_dom::RealDom;
use crate::tree::{SlabEntry, Tree, TreeStateView}; use crate::tree::{SlabEntry, Tree, TreeStateView};
use crate::{FxDashMap, FxDashSet, SendAnyMap}; use crate::{FxDashSet, SendAnyMap};
use crate::{NodeId, NodeMask}; use crate::{NodeId, NodeMask};
#[derive(Default)] #[derive(Default)]
@@ -47,76 +47,58 @@ impl DirtyNodes {
} }
} }
#[derive(Default, Clone)] #[derive(Clone)]
pub struct DirtyNodeStates { pub struct DirtyNodeStates {
dirty: Arc<RwLock<BTreeMap<u16, FxDashMap<TypeId, DirtyNodes>>>>, dirty: Arc<FxHashMap<TypeId, RwLock<BTreeMap<u16, DirtyNodes>>>>,
} }
impl DirtyNodeStates { impl DirtyNodeStates {
pub fn with_passes(passes: impl Iterator<Item = TypeId>) -> Self {
let mut dirty = FxHashMap::default();
for pass in passes {
dirty.insert(pass, RwLock::new(BTreeMap::new()));
}
Self {
dirty: Arc::new(dirty),
}
}
pub fn insert(&self, pass_id: TypeId, node_id: NodeId, height: u16) { pub fn insert(&self, pass_id: TypeId, node_id: NodeId, height: u16) {
let mut dirty = self.dirty.write(); let btree = self.dirty.get(&pass_id).unwrap();
if let Some(dirty) = dirty.get_mut(&height) { let mut write = btree.write();
if let Some(mut entry) = dirty.get_mut(&pass_id) { if let Some(entry) = write.get_mut(&height) {
entry.add_node(node_id); entry.add_node(node_id);
} else {
let mut entry = DirtyNodes::default();
entry.add_node(node_id);
dirty.insert(pass_id, entry);
}
} else { } else {
let mut entry = DirtyNodes::default(); let mut entry = DirtyNodes::default();
entry.add_node(node_id); entry.add_node(node_id);
let hm = FxDashMap::default(); write.insert(height, entry);
hm.insert(pass_id, entry);
dirty.insert(height, hm);
} }
} }
fn pop_front(&self, pass_id: TypeId) -> Option<(u16, NodeId)> { fn pop_front(&self, pass_id: TypeId) -> Option<(u16, NodeId)> {
let dirty_read = self.dirty.read(); let mut values = self.dirty.get(&pass_id)?.write();
let (&height, values) = dirty_read let mut value = values.first_entry()?;
.iter() let height = *value.key();
.find(|(_, values)| values.contains_key(&pass_id))?; let ids = value.get_mut();
let node_id = { let id = ids.pop()?;
let mut dirty = values.get_mut(&pass_id)?; if ids.is_empty() {
let node_id = dirty.pop()?; value.remove_entry();
if dirty.is_empty() {
drop(dirty);
values.remove(&pass_id);
}
node_id
};
if values.is_empty() {
drop(dirty_read);
let mut dirty_write = self.dirty.write();
dirty_write.remove(&height);
} }
Some((height, node_id)) Some((height, id))
} }
fn pop_back(&self, pass_id: TypeId) -> Option<(u16, NodeId)> { fn pop_back(&self, pass_id: TypeId) -> Option<(u16, NodeId)> {
let dirty_read = self.dirty.read(); let mut values = self.dirty.get(&pass_id)?.write();
let (&height, values) = dirty_read let mut value = values.last_entry()?;
.iter() let height = *value.key();
.rev() let ids = value.get_mut();
.find(|(_, values)| values.contains_key(&pass_id))?; let id = ids.pop()?;
let node_id = { if ids.is_empty() {
let mut dirty = values.get_mut(&pass_id)?; value.remove_entry();
let node_id = dirty.pop()?;
if dirty.is_empty() {
drop(dirty);
values.remove(&pass_id);
}
node_id
};
if values.is_empty() {
drop(dirty_read);
let mut dirty_write = self.dirty.write();
dirty_write.remove(&height);
} }
Some((height, node_id)) Some((height, id))
} }
} }
@@ -184,10 +166,10 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
parent_dependant: !Self::parent_type_ids().is_empty(), parent_dependant: !Self::parent_type_ids().is_empty(),
child_dependant: !Self::child_type_ids().is_empty(), child_dependant: !Self::child_type_ids().is_empty(),
dependants: FxHashSet::default(), dependants: FxHashSet::default(),
mask: node_mask, mask: node_mask.clone(),
pass_direction: Self::pass_direction(), pass_direction: Self::pass_direction(),
pass: Box::new( pass: Box::new(
|node_id: NodeId, tree: &mut TreeStateView, context: &SendAnyMap| { move |node_id: NodeId, tree: &mut TreeStateView, context: &SendAnyMap| {
debug_assert!(!Self::NodeDependencies::type_ids() debug_assert!(!Self::NodeDependencies::type_ids()
.iter() .iter()
.any(|id| *id == TypeId::of::<Self>())); .any(|id| *id == TypeId::of::<Self>()));
@@ -203,7 +185,7 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
if myself.value.is_none() { if myself.value.is_none() {
*myself.value = Some(Self::create( *myself.value = Some(Self::create(
NodeView::new(node_data, Self::NODE_MASK.build()), NodeView::new(node_data, &node_mask),
node, node,
parent, parent,
children, children,
@@ -212,7 +194,7 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
true true
} else { } else {
myself.value.as_mut().unwrap().pass( myself.value.as_mut().unwrap().pass(
NodeView::new(node_data, Self::NODE_MASK.build()), NodeView::new(node_data, &node_mask),
node, node,
parent, parent,
children, children,
@@ -290,7 +272,7 @@ impl<V: FromAnyValue + Send> TypeErasedPass<V> {
nodes_updated.insert(id); nodes_updated.insert(id);
for id in tree.children_ids(id).unwrap() { for id in tree.children_ids(id).unwrap() {
for dependant in &self.dependants { for dependant in &self.dependants {
dirty.insert(*dependant, id, height + 1); dirty.insert(*dependant, *id, height + 1);
} }
} }
} }
+1 -1
View File
@@ -442,7 +442,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) { ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
let passes = std::mem::take(&mut self.passes_updated); let passes = std::mem::take(&mut self.passes_updated);
let nodes_updated = std::mem::take(&mut self.nodes_updated); let nodes_updated = std::mem::take(&mut self.nodes_updated);
let dirty_nodes = DirtyNodeStates::default(); let dirty_nodes = DirtyNodeStates::with_passes(self.passes.iter().map(|p| p.this_type_id));
for (node_id, passes) in passes { for (node_id, passes) in passes {
// remove any nodes that were created and then removed in the same mutations from the dirty nodes list // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
if let Some(height) = self.tree.height(node_id) { if let Some(height) = self.tree.height(node_id) {
+2 -2
View File
@@ -277,8 +277,8 @@ impl<'a, 'b> TreeStateView<'a, 'b> {
}) })
} }
pub fn children_ids(&self, id: NodeId) -> Option<Vec<NodeId>> { pub fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
self.nodes_data.get(id).map(|node| node.children.clone()) self.nodes_data.get(id).map(|node| &*node.children)
} }
pub fn parent_id(&self, id: NodeId) -> Option<NodeId> { pub fn parent_id(&self, id: NodeId) -> Option<NodeId> {