feature: runtime cache for running a batch of node

main
taoria 3 years ago
parent 00a423e2ab
commit e8947b7df4
  1. 5
      TNode/TNodeCore/Runtime/Attribute/Ports/BatchInputAttribute.cs
  2. 0
      TNode/TNodeCore/Runtime/Attributes.meta
  3. 0
      TNode/TNodeCore/Runtime/Attributes/DisableOnInspector.cs
  4. 0
      TNode/TNodeCore/Runtime/Attributes/DisableOnInspector.cs.meta
  5. 0
      TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs
  6. 0
      TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs.meta
  7. 0
      TNode/TNodeCore/Runtime/Attributes/InternalUsageAttribute.cs
  8. 0
      TNode/TNodeCore/Runtime/Attributes/InternalUsageAttribute.cs.meta
  9. 0
      TNode/TNodeCore/Runtime/Attributes/NodeAttribute.cs
  10. 0
      TNode/TNodeCore/Runtime/Attributes/NodeAttribute.cs.meta
  11. 0
      TNode/TNodeCore/Runtime/Attributes/PortTypeConversion.cs
  12. 0
      TNode/TNodeCore/Runtime/Attributes/PortTypeConversion.cs.meta
  13. 0
      TNode/TNodeCore/Runtime/Attributes/Ports.meta
  14. 5
      TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs
  15. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/BatchInputAttribute.cs.meta
  16. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/BatchOutputAttribute.cs
  17. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/BatchOutputAttribute.cs.meta
  18. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs
  19. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs.meta
  20. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs
  21. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs.meta
  22. 1
      TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs
  23. 0
      TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs.meta
  24. 0
      TNode/TNodeCore/Runtime/Attributes/RuntimeNodeAttribute.cs
  25. 0
      TNode/TNodeCore/Runtime/Attributes/RuntimeNodeAttribute.cs.meta
  26. 0
      TNode/TNodeCore/Runtime/Attributes/ShowInNodeViewAttribute.cs
  27. 0
      TNode/TNodeCore/Runtime/Attributes/ShowInNodeViewAttribute.cs.meta
  28. 0
      TNode/TNodeCore/Runtime/Attributes/ViewComponentAttribute.cs
  29. 0
      TNode/TNodeCore/Runtime/Attributes/ViewComponentAttribute.cs.meta
  30. 65
      TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs
  31. 3
      TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs
  32. 2
      TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs
  33. 5
      TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs

@ -1,5 +0,0 @@
namespace TNodeCore.Attribute.Ports{
public class BatchInputAttribute{
}
}

@ -0,0 +1,5 @@
namespace TNode.TNodeCore.Runtime.Attributes.Ports{
public class BatchInputAttribute{
}
}

@ -22,6 +22,7 @@ namespace TNodeCore.Attribute.Ports{
public readonly string Name; public readonly string Name;
public readonly PortNameHandling NameHandling; public readonly PortNameHandling NameHandling;
public Type HandledType; public Type HandledType;
public bool Multiple = true;
public TypeHandling TypeHandling{ get; set; } public TypeHandling TypeHandling{ get; set; }
public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared){ public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared){
this.Name = name; this.Name = name;

@ -17,6 +17,8 @@ namespace TNodeCore.Components{
[NonSerialized] [NonSerialized]
public readonly List<RuntimeNode> TopologicalOrder = new List<RuntimeNode>(); public readonly List<RuntimeNode> TopologicalOrder = new List<RuntimeNode>();
public readonly List<RuntimeNode> EntryNodes = new List<RuntimeNode>(); public readonly List<RuntimeNode> EntryNodes = new List<RuntimeNode>();
public readonly Dictionary<string, object> OutputCached = new Dictionary<string, object>();
private bool _isCachingOutput = false;
/// <summary> /// <summary>
/// elements are read only ,do not modify them /// elements are read only ,do not modify them
/// </summary> /// </summary>
@ -30,24 +32,52 @@ namespace TNodeCore.Components{
node.NodeData.Process(); node.NodeData.Process();
} }
} }
public void DependencyTraversal(RuntimeNode runtimeNode){ //Cache outport info in the graph tool so that we can directly access it in the traversal
public void StartCachingPort(){
_isCachingOutput = true;
}
public void EndCachingPort(){
_isCachingOutput = false;
OutputCached.Clear();
}
public void ResolveDependency(RuntimeNode runtimeNode,int dependencyLevel=0){
var links = runtimeNode.InputLink; var links = runtimeNode.InputLink;
foreach (var link in links){ foreach (var link in links){
var outputNode = RuntimeNodes[link.outPort.nodeDataId]; var outputNode = RuntimeNodes[link.outPort.nodeDataId];
DependencyTraversal(outputNode); ResolveDependency(outputNode,dependencyLevel+1);
HandlingLink(link); HandlingLink(link);
} }
if (dependencyLevel > DependencyLevelMax){
throw new Exception("Dependency anomaly detected,check if there is a loop in the graph");
}
//if the runtime node has no output ,it will not be processed
if (runtimeNode.OutputLink.Count == 0 && dependencyLevel != 0){
return;
}
runtimeNode.NodeData.Process(); runtimeNode.NodeData.Process();
} }
private const int DependencyLevelMax = 1145;
public void HandlingLink(NodeLink nodeLink){ public void HandlingLink(NodeLink nodeLink){
//out node is node output data
//in node is node receive data
var inNode = RuntimeNodes[nodeLink.inPort.nodeDataId]; var inNode = RuntimeNodes[nodeLink.inPort.nodeDataId];
var outNode = RuntimeNodes[nodeLink.outPort.nodeDataId]; var outNode = RuntimeNodes[nodeLink.outPort.nodeDataId];
//out node is node output data
//in node is node receive data //TODO looks like this string would be too long to make a cache
var outValue = outNode.GetOutput(nodeLink.outPort.portEntryName);
var cachedKey = $"{outNode.NodeData.id}-{nodeLink.inPort.portEntryName}";
var outValue = OutputCached.ContainsKey(cachedKey) ? OutputCached[cachedKey] : outNode.GetOutput(nodeLink.outPort.portEntryName);;
if (_isCachingOutput){
OutputCached[cachedKey] = outValue;
}
inNode.SetInput(nodeLink.inPort.portEntryName, outValue); inNode.SetInput(nodeLink.inPort.portEntryName, outValue);
} }
public GraphTool(List<RuntimeNode> list, Dictionary<string, RuntimeNode> graphNodes){ public GraphTool(List<RuntimeNode> list, Dictionary<string, RuntimeNode> graphNodes){
@ -125,12 +155,12 @@ namespace TNodeCore.Components{
return null; return null;
} }
//DFS search for resolving dependency //DFS search for resolving dependency
public bool ResolveDependency(NodeData startNode){ public bool RunOnDependency(NodeData startNode){
if(!_build) if(!_build)
Build(); Build();
if (_graphTool == null) if (_graphTool == null)
return false; return false;
_graphTool.DependencyTraversal(Get(startNode)); _graphTool.ResolveDependency(Get(startNode));
return true; return true;
} }
public bool ResolveDependency(){ public bool ResolveDependency(){
@ -152,10 +182,20 @@ namespace TNodeCore.Components{
} }
public List<RuntimeNode> GetRuntimeNodesOfType<T>(){ public List<RuntimeNode> GetRuntimeNodesOfType<T>(){
return RuntimeNodes.Values.Where(x => x.NodeType == typeof(T)).ToList(); return RuntimeNodes.Values.Where(x => typeof(T).IsAssignableFrom(x.NodeType)).ToList();
} }
public List<RuntimeNode> GetRuntimeNodesOfType(Type type){ public List<RuntimeNode> GetRuntimeNodesOfType(Type type){
return RuntimeNodes.Values.Where(x => x.NodeType == type).ToList(); return RuntimeNodes.Values.Where(x => type.IsAssignableFrom(type)).ToList();
}
public void RunNodesOfType(Type t){
var nodes = GetRuntimeNodesOfType(t);
_graphTool.StartCachingPort();
foreach (var runtimeNode in nodes){
RunOnDependency(runtimeNode.NodeData);
}
_graphTool.EndCachingPort();
} }
private void ModifyOrCreateOutNode(NodeLink linkData){ private void ModifyOrCreateOutNode(NodeLink linkData){
var outNodeId = linkData.outPort.nodeDataId; var outNodeId = linkData.outPort.nodeDataId;
@ -170,7 +210,7 @@ namespace TNodeCore.Components{
public void OnValidate(){ public void OnValidate(){
if(runtimeBlackboardData==null||runtimeBlackboardData.GetType()==typeof(BlackboardData)){ if(runtimeBlackboardData==null||runtimeBlackboardData.GetType()==typeof(BlackboardData)){
if (graphData != null) if (graphData != null)
runtimeBlackboardData = graphData.blackboardData.Clone() as BlackboardData; runtimeBlackboardData = graphData.blackboardData?.Clone() as BlackboardData;
} }
} }
@ -186,6 +226,7 @@ namespace TNodeCore.Components{
public void Start(){ public void Start(){
Build(); Build();
} }
public virtual void RuntimeExecute(){ public virtual void RuntimeExecute(){
_graphTool.DirectlyTraversal(); _graphTool.DirectlyTraversal();

@ -267,6 +267,9 @@ namespace TNodeCore.RuntimeCache{
return (T) method.Invoke(data); return (T) method.Invoke(data);
} }
public static object GetValue(this IModel data, string path,Type type=null){ public static object GetValue(this IModel data, string path,Type type=null){
if(!RuntimeCache.Instance.CachedDelegatesForGettingValue.ContainsKey(type??data.GetType())){
return null;
}
var dic = RuntimeCache.Instance.CachedDelegatesForGettingValue[type ?? data.GetType()]; var dic = RuntimeCache.Instance.CachedDelegatesForGettingValue[type ?? data.GetType()];
var method = dic.ContainsKey(path) ? dic[path] : null; var method = dic.ContainsKey(path) ? dic[path] : null;
return method?.Invoke(data); return method?.Invoke(data);

@ -80,7 +80,7 @@ namespace TNode.Editor.Inspector{
if(!test.IsRuntimeGraph) return; if(!test.IsRuntimeGraph) return;
var runtimeGraph = test.GetRuntimeGraph(); var runtimeGraph = test.GetRuntimeGraph();
if (runtimeGraph != null){ if (runtimeGraph != null){
var res = runtimeGraph.ResolveDependency(_data); var res = runtimeGraph.RunOnDependency(_data);
} }
_data.OnTest(); _data.OnTest();
} }

@ -105,7 +105,8 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{
foreach (var propertyInfo in propertyInfos){ foreach (var propertyInfo in propertyInfos){
if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){ if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){
Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,BuildPortType(attribute,propertyInfo));
Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo));
this.outputContainer.Add(port); this.outputContainer.Add(port);
var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute,propertyInfo)); var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute,propertyInfo));
port.portName = portName; port.portName = portName;
@ -115,7 +116,7 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{
} }
foreach (var propertyInfo in propertyInfos){ foreach (var propertyInfo in propertyInfos){
if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){ if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){
Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,Port.Capacity.Single,BuildPortType(attribute,propertyInfo)); Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo));
this.inputContainer.Add(port); this.inputContainer.Add(port);
var portName = BuildPortName(attribute,propertyInfo); var portName = BuildPortName(attribute,propertyInfo);
port.portName = portName; port.portName = portName;

Loading…
Cancel
Save