Skip to content

Commit de327ba

Browse files
DYN-8310 - speed up graph open by caching category getter (#16151)
Co-authored-by: Bendik Tobias Berg <bendik@reope.com>
1 parent 1f25b60 commit de327ba

2 files changed

Lines changed: 58 additions & 30 deletions

File tree

src/DynamoCore/Library/FunctionDescriptor.cs

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.IO;
45
using System.Linq;
56
using System.Reflection;
@@ -68,7 +69,9 @@ public FunctionDescriptorParams()
6869
}
6970

7071
/// <summary>
71-
/// Returns full path to the assembly the defined this function
72+
/// Returns full path to the assembly the defined this function.
73+
/// This is not always an assembly path, it might be a path to a .ds file
74+
/// or builtin token like 'operators'.
7275
/// </summary>
7376
public string Assembly { get; set; }
7477

@@ -221,7 +224,9 @@ public FunctionDescriptor(FunctionDescriptorParams funcDescParams)
221224
public bool IsOverloaded { get; set; }
222225

223226
/// <summary>
224-
/// Full path to the assembly which defined this function
227+
/// Returns full path to the assembly the defined this function.
228+
/// This is not always an assembly path, it might be a path to a .ds file
229+
/// or builtin token like 'operators'.
225230
/// </summary>
226231
public string Assembly { get; private set; }
227232

@@ -318,49 +323,71 @@ public IEnumerable<Tuple<string, string>> InputParameters
318323
private set;
319324
}
320325

326+
private string category;
321327
/// <summary>
322328
/// The category of this function.
323329
/// </summary>
324330
public string Category
325331
{
326332
get
327333
{
334+
if (category != null)
335+
{
336+
return category;
337+
}
328338
var categoryBuf = new StringBuilder();
329339
categoryBuf.Append(GetRootCategory());
330340

331-
//if this is not BuiltIn function search NodeCategoryAttribute for it
332-
if (ClassName != null)
341+
//if this is not BuiltIn function and not a function defined in a .ds file
342+
//search the containing assembly for the NodeCategoryAttribute.
343+
if (ClassName != null &&
344+
Assembly!=null && !Assembly.ToLowerInvariant().EndsWith(".ds"))
333345
{
334-
//get function assembly
335-
var asm = AppDomain.CurrentDomain.GetAssemblies()
336-
.Where(x => x.GetName().Name == Path.GetFileNameWithoutExtension(Assembly))
337-
.ToArray();
338-
339-
if (asm.Any() && asm.First().GetType(ClassName) != null)
346+
try
340347
{
341-
//get class type of function
342-
var type = asm.First().GetType(ClassName);
343-
344-
//get NodeCategoryAttribute for this function if it was been defined
345-
var nodeCat = type.GetMethods().Where(x => x.Name == FunctionName)
346-
.Select(x => x.GetCustomAttribute(typeof(NodeCategoryAttribute)))
347-
.Where(x => x != null)
348-
.Cast<NodeCategoryAttribute>()
349-
.Select(x => x.ElementCategory)
350-
.FirstOrDefault();
351-
352-
//if attribute is found compose node category string with last part from attribute
353-
if (!string.IsNullOrEmpty(nodeCat) && (
354-
nodeCat == LibraryServices.Categories.Constructors
355-
|| nodeCat == LibraryServices.Categories.Properties
356-
|| nodeCat == LibraryServices.Categories.MemberFunctions))
348+
#if DEBUG
349+
var LoadedAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Length;
350+
#endif
351+
var asm = AppDomain.CurrentDomain.Load(Path.GetFileNameWithoutExtension(Assembly));
352+
#if DEBUG
353+
354+
Debug.Assert(AppDomain.CurrentDomain.GetAssemblies().Length == LoadedAssemblyCount,
355+
"Assembly count should not have changed, because should not have actually performed a load.");
356+
357+
#endif
358+
if (asm != null)
357359
{
358-
categoryBuf.Append("." + UnqualifedClassName + "." + nodeCat);
359-
return categoryBuf.ToString();
360+
//get class type of function
361+
var type = asm.GetType(ClassName);
362+
if (type != null)
363+
{
364+
//get NodeCategoryAttribute for this function if it was defined
365+
var nodeCat = type.GetMethods().Where(x => x.Name == FunctionName)
366+
.Select(x => x.GetCustomAttribute(typeof(NodeCategoryAttribute)))
367+
.Where(x => x != null)
368+
.Cast<NodeCategoryAttribute>()
369+
.Select(x => x.ElementCategory)
370+
.FirstOrDefault();
371+
372+
//if attribute is found compose node category string with last part from attribute
373+
if (!string.IsNullOrEmpty(nodeCat) && (
374+
nodeCat == LibraryServices.Categories.Constructors
375+
|| nodeCat == LibraryServices.Categories.Properties
376+
|| nodeCat == LibraryServices.Categories.MemberFunctions))
377+
{
378+
categoryBuf.Append("." + UnqualifedClassName + "." + nodeCat);
379+
category = categoryBuf.ToString();
380+
return category;
381+
}
382+
}
360383
}
361384
}
385+
catch (Exception e)
386+
{
387+
//TODO ideally this would surface to dynamo logger somehow.
388+
Console.WriteLine($"Error while generating function descriptor category:{Assembly} {ClassName} {FunctionName} {e}");
389+
}
362390
}
363-
364391
switch (Type)
365392
{
366393
case FunctionType.Constructor:
@@ -583,7 +610,7 @@ private bool CheckIfFunctionIsMarkedExperimentalByPrefs(FunctionDescriptor fd)
583610
}
584611
return false;
585612
}
586-
internal bool IsExperimental { get;}
613+
internal bool IsExperimental { get; }
587614
}
588615

589616
}

src/DynamoCore/Models/DynamoModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3507,6 +3507,7 @@ internal void AddZeroTouchNodesToSearch(IEnumerable<FunctionGroup> functionGroup
35073507
{
35083508
var iDoc = LuceneUtility.InitializeIndexDocumentForNodes();
35093509
List<NodeSearchElement> nodes = new();
3510+
35103511
foreach (var funcGroup in functionGroups)
35113512
{
35123513
foreach (var functionDescriptor in funcGroup.Functions)

0 commit comments

Comments
 (0)