improve performance
This commit is contained in:
1 parent
71a0bdf71d
commit
d67b21c0e9
4 files changed
+45
-63
No files matched your search
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
Reference in new issue
Block a user