Refactor document node type lookup function to fix performance degradation over time (#1878)

* Refactor document_node_types function

* Fix node introspection

* Implement diff based type updates

* Fix missing monitor nodes

* Improve docs and fix warings

* Fix wrongful removal of node paths

* Remove code examples for non pub methodsü

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-08-09 02:37:28 +02:00
committed by GitHub
parent 06a409f1c5
commit 0dfddd529b
25 changed files with 460 additions and 282 deletions

View File

@@ -227,8 +227,7 @@ pub struct OriginalLocation {
pub path: Option<Vec<NodeId>>,
/// Each document input source maps to one proto node input (however one proto node input may come from several sources)
pub inputs_source: HashMap<Source, usize>,
/// A list of document sources for the node's output
pub outputs_source: HashMap<Source, usize>,
/// A list of flags indicating whether the input is exposed in the UI
pub inputs_exposed: Vec<bool>,
/// Skipping inputs is useful for the manual composition thing - whereby a hidden `Footprint` input is added as the first input.
pub skip_inputs: usize,
@@ -251,7 +250,6 @@ impl Hash for OriginalLocation {
fn hash<H: Hasher>(&self, state: &mut H) {
self.path.hash(state);
self.inputs_source.iter().for_each(|val| val.hash(state));
self.outputs_source.iter().for_each(|val| val.hash(state));
self.inputs_exposed.hash(state);
self.skip_inputs.hash(state);
}
@@ -266,14 +264,6 @@ impl OriginalLocation {
.flatten()
.chain(self.inputs_source.iter().filter(move |x| *x.1 == index).map(|(source, _)| source.clone()))
}
pub fn outputs(&self, index: usize) -> impl Iterator<Item = Source> + '_ {
[Source {
node: self.path.clone().unwrap_or_default(),
index,
}]
.into_iter()
.chain(self.outputs_source.iter().filter(move |x| *x.1 == index).map(|(source, _)| source.clone()))
}
}
impl DocumentNode {
/// Locate the input that is a [`NodeInput::Network`] at index `offset` and replace it with a [`NodeInput::Node`].
@@ -1161,11 +1151,6 @@ impl NodeNetwork {
if let NodeInput::Node { node_id, output_index, .. } = &export {
self.replace_node_inputs(node_input(id, i, false), node_input(*node_id, *output_index, false));
self.replace_node_inputs(node_input(id, i, true), node_input(*node_id, *output_index, true));
if let Some(new_output_node) = self.nodes.get_mut(node_id) {
for source in node.original_location.outputs(i) {
new_output_node.original_location.outputs_source.insert(source, *output_index);
}
}
}
self.replace_network_outputs(NodeInput::node(id, i), export);
@@ -1197,11 +1182,6 @@ impl NodeNetwork {
assert_eq!(node.inputs.len(), 1, "Id node has more than one input");
if let NodeInput::Node { node_id, output_index, .. } = node.inputs[0] {
let node_input_output_index = output_index;
if let Some(input_node) = self.nodes.get_mut(&node_id) {
for source in node.original_location.outputs(0) {
input_node.original_location.outputs_source.insert(source, node_input_output_index);
}
}
let input_node_id = node_id;
for output in self.nodes.values_mut() {
@@ -1507,7 +1487,6 @@ mod test {
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(0)]),
inputs_source: [(Source { node: vec![NodeId(1)], index: 1 }, 1)].into(),
outputs_source: HashMap::new(),
inputs_exposed: vec![true, true],
skip_inputs: 0,
},
@@ -1524,7 +1503,6 @@ mod test {
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(1)]),
inputs_source: HashMap::new(),
outputs_source: [(Source { node: vec![NodeId(1)], index: 0 }, 0)].into(),
inputs_exposed: vec![true],
skip_inputs: 0,
},
@@ -1540,7 +1518,6 @@ mod test {
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(4)]),
inputs_source: HashMap::new(),
outputs_source: HashMap::new(),
inputs_exposed: vec![true, false],
skip_inputs: 0,
},
@@ -1571,7 +1548,6 @@ mod test {
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(0)]),
inputs_source: [(Source { node: vec![NodeId(1)], index: 1 }, 1)].into(),
outputs_source: HashMap::new(),
inputs_exposed: vec![true, true],
skip_inputs: 0,
},
@@ -1586,7 +1562,6 @@ mod test {
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(4)]),
inputs_source: HashMap::new(),
outputs_source: HashMap::new(),
inputs_exposed: vec![true, false],
skip_inputs: 0,
},
@@ -1601,7 +1576,6 @@ mod test {
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(1)]),
inputs_source: HashMap::new(),
outputs_source: [(Source { node: vec![NodeId(1)], index: 0 }, 0)].into(),
inputs_exposed: vec![true],
skip_inputs: 0,
},

View File

@@ -25,7 +25,7 @@ impl std::cmp::PartialEq for ImaginateCache {
impl core::hash::Hash for ImaginateCache {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.0.try_lock().map(|g| g.hash(state));
let _ = self.0.try_lock().map(|g| g.hash(state)).map_err(|_| "error".hash(state));
}
}

View File

@@ -349,6 +349,18 @@ impl ProtoNetwork {
);
}
#[cfg(debug_assertions)]
pub fn example() -> (Self, NodeId, ProtoNode) {
let node_id = NodeId(1);
let proto_node = ProtoNode::default();
let proto_network = ProtoNetwork {
inputs: vec![node_id],
output: node_id,
nodes: vec![(node_id, proto_node.clone())],
};
(proto_network, node_id, proto_node)
}
/// Construct a hashmap containing a list of the nodes that depend on this proto network.
pub fn collect_outwards_edges(&self) -> HashMap<NodeId, Vec<NodeId>> {
let mut edges: HashMap<NodeId, Vec<NodeId>> = HashMap::new();
@@ -675,20 +687,18 @@ impl TypingContext {
/// and store them in the `inferred` field. The proto network has to be topologically sorted
/// and contain fully resolved stable node ids.
pub fn update(&mut self, network: &ProtoNetwork) -> Result<(), GraphErrors> {
let mut deleted_nodes = self.inferred.keys().copied().collect::<HashSet<_>>();
for (id, node) in network.nodes.iter() {
self.infer(*id, node)?;
deleted_nodes.remove(id);
}
for node in deleted_nodes {
self.inferred.remove(&node);
}
Ok(())
}
pub fn remove_inference(&mut self, node_id: NodeId) -> Option<NodeIOTypes> {
self.constructor.remove(&node_id);
self.inferred.remove(&node_id)
}
/// Returns the node constructor for a given node id.
pub fn constructor(&self, node_id: NodeId) -> Option<NodeConstructor> {
self.constructor.get(&node_id).copied()

View File

@@ -103,13 +103,13 @@ impl WasmApplicationIo {
ids: AtomicU64::new(0),
#[cfg(feature = "wgpu")]
gpu_executor: executor,
windows: Vec::new().into(),
windows: Vec::new(),
resources: HashMap::new(),
};
#[cfg(not(feature = "ci"))]
let window = io.create_window();
#[cfg(not(feature = "ci"))]
io.windows.push(WindowWrapper { window });
if cfg!(target_arch = "wasm32") {
let window = io.create_window();
io.windows.push(WindowWrapper { window });
}
io.resources.insert("null".to_string(), Arc::from(include_bytes!("null.png").to_vec()));
io
@@ -267,7 +267,7 @@ impl ApplicationIo for WasmApplicationIo {
}
fn window(&self) -> Option<SurfaceHandle<Self::Surface>> {
self.windows.iter().next().map(|wrapper| wrapper.window.clone())
self.windows.first().map(|wrapper| wrapper.window.clone())
}
}