mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
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:
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user