From 6da891285b63f37e1a7a97ff075c5846876df1b5 Mon Sep 17 00:00:00 2001 From: Marius Bughiu Date: Sat, 2 Aug 2025 18:03:33 +0300 Subject: [PATCH 1/2] Optimize TryGetArgumentDirectionAndType --- .../ActivityUtilities.cs | 25 +++++++++++++++++++ src/UiPath.Workflow.Runtime/AssemblyInfo.cs | 1 + 2 files changed, 26 insertions(+) diff --git a/src/UiPath.Workflow.Runtime/ActivityUtilities.cs b/src/UiPath.Workflow.Runtime/ActivityUtilities.cs index 40bf4219..e722080e 100644 --- a/src/UiPath.Workflow.Runtime/ActivityUtilities.cs +++ b/src/UiPath.Workflow.Runtime/ActivityUtilities.cs @@ -10,6 +10,7 @@ namespace System.Activities; using Expressions; using Internals; using Runtime; +using System.Collections.Concurrent; using Validation; internal static class ActivityUtilities @@ -47,6 +48,8 @@ internal static class ActivityUtilities private static readonly Type outArgumentOfObjectType = typeof(OutArgument); private static readonly Type inOutArgumentOfObjectType = typeof(InOutArgument); private static PropertyChangedEventArgs propertyChangedEventArgs; + + private static readonly ConcurrentDictionary argumentTypeCache = new(); // Can't delay create this one because we use object.ReferenceEquals on it in WorkflowInstance private static readonly ReadOnlyDictionary emptyParameters = new(new Dictionary(0)); @@ -97,6 +100,18 @@ public static bool IsInScope(ActivityInstance potentialChild, ActivityInstance s public static bool IsCompletedState(ActivityInstanceState state) => state != ActivityInstanceState.Executing; + private readonly struct ArgumentTypeInfo + { + public readonly ArgumentDirection Direction; + public readonly Type ArgumentType; + + public ArgumentTypeInfo(ArgumentDirection direction, Type argumentType) + { + Direction = direction; + ArgumentType = argumentType; + } + } + public static bool TryGetArgumentDirectionAndType(Type propertyType, out ArgumentDirection direction, out Type argumentType) { direction = ArgumentDirection.In; // default to In @@ -104,24 +119,34 @@ public static bool TryGetArgumentDirectionAndType(Type propertyType, out Argumen if (propertyType.IsGenericType) { + if (argumentTypeCache.TryGetValue(propertyType, out ArgumentTypeInfo info)) + { + direction = info.Direction; + argumentType = info.ArgumentType; + return true; + } + argumentType = propertyType.GetGenericArguments()[0]; Type genericType = propertyType.GetGenericTypeDefinition(); if (genericType == inArgumentGenericType) { + argumentTypeCache.TryAdd(propertyType, new ArgumentTypeInfo(direction, argumentType)); return true; } if (genericType == outArgumentGenericType) { direction = ArgumentDirection.Out; + argumentTypeCache.TryAdd(propertyType, new ArgumentTypeInfo(direction, argumentType)); return true; } if (genericType == inOutArgumentGenericType) { direction = ArgumentDirection.InOut; + argumentTypeCache.TryAdd(propertyType, new ArgumentTypeInfo(direction, argumentType)); return true; } } diff --git a/src/UiPath.Workflow.Runtime/AssemblyInfo.cs b/src/UiPath.Workflow.Runtime/AssemblyInfo.cs index 86237715..42a60e36 100644 --- a/src/UiPath.Workflow.Runtime/AssemblyInfo.cs +++ b/src/UiPath.Workflow.Runtime/AssemblyInfo.cs @@ -28,4 +28,5 @@ [assembly: InternalsVisibleTo("UiPath.Workflow")] [assembly: InternalsVisibleTo("TestCases.Workflows")] [assembly: InternalsVisibleTo("TestCases.Runtime")] +[assembly: InternalsVisibleTo("CoreWf.Benchmarks")] [assembly: InternalsVisibleTo("Perf.AssemblyReference.Benchmarks")] From 11e113b91cb11c4c61a24a166eb1334afac73780 Mon Sep 17 00:00:00 2001 From: Marius Bughiu Date: Mon, 4 Aug 2025 20:47:53 +0300 Subject: [PATCH 2/2] force aggressive inlining --- src/UiPath.Workflow.Runtime/ActivityUtilities.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/UiPath.Workflow.Runtime/ActivityUtilities.cs b/src/UiPath.Workflow.Runtime/ActivityUtilities.cs index e722080e..5c7cc7eb 100644 --- a/src/UiPath.Workflow.Runtime/ActivityUtilities.cs +++ b/src/UiPath.Workflow.Runtime/ActivityUtilities.cs @@ -11,6 +11,7 @@ namespace System.Activities; using Internals; using Runtime; using System.Collections.Concurrent; +using System.Runtime.CompilerServices; using Validation; internal static class ActivityUtilities @@ -112,6 +113,7 @@ public ArgumentTypeInfo(ArgumentDirection direction, Type argumentType) } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryGetArgumentDirectionAndType(Type propertyType, out ArgumentDirection direction, out Type argumentType) { direction = ArgumentDirection.In; // default to In