From c2fcc543a455c9856580eac5d4d79b220ea1e82c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 17 Oct 2018 16:35:30 +0200 Subject: [PATCH] [Class] Cache the IntPtr constructors in a dictionary. Using reflection to find these constructors is computation-intensitive, so cache the results. Numbers ======= Test case: https://github.com/rolfbjarne/TestApp/commit/004283d7b628a29fcf711d98d8842bfd4ef4393b Fix 1 refers to PR #5009. Fix 2 refers to PR #5013. Fix 3 is this fix. iPad Air 2 ---------- | Configuration | Before | After fix 1 | After fix 2 | After fix 3 | Improvement from fix 2 to fix 3 | Cumulative improvement | | ------------------- | ------ | ----------: | -----------: | -----------: | ------------------------------: | ---------------------: | | Release (link all) | 477 ms | 481 ms | 224 ms | 172 ms | 52 ms (23%) | 305 ms (64%) | | Release (dont link) | 738 ms | 656 ms | 377 ms | 201 ms | 176 ms (47%) | 537 ms (73%) | iPhone X -------- | Configuration | Before | After fix 1 | After fix 2 | After fix 3 | Improvement from fix 2 to fix 3 | Cumulative improvement | | ------------------- | ------ | ----------: | -----------: | -----------: | ------------------------------: | ---------------------: | | Release (link all) | 98 ms | 99 ms | 42 ms | 31 ms | 11 ms (26%) | 67 ms (68%) | | Release (dont link) | 197 ms | 153 ms | 91 ms | 43 ms | 48 ms (53%) | 154 ms (78%) | When linking all assemblies, the type map has 24 entries, and when not linking at all it has 2993 entries. This is part 3 of multiple fixes for #4936. --- src/ObjCRuntime/Runtime.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index 12501fe4731e..26a0d45fcadf 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -39,6 +39,8 @@ public partial class Runtime { #endif static Dictionary block_to_delegate_cache; + static Dictionary intptr_ctor_cache; + static Dictionary intptr_bool_ctor_cache; static List delegates; static List assemblies; @@ -239,6 +241,8 @@ unsafe static void Initialize (InitializationOptions* options) Runtime.options = options; delegates = new List (); object_map = new Dictionary (IntPtrEqualityComparer); + intptr_ctor_cache = new Dictionary (TypeEqualityComparer); + intptr_bool_ctor_cache = new Dictionary (TypeEqualityComparer); lock_obj = new object (); NSObjectClass = NSObject.Initialize (); @@ -1152,22 +1156,36 @@ static T ConstructINativeObject (IntPtr ptr, bool owns, Type type, MissingCto static ConstructorInfo GetIntPtrConstructor (Type type) { + lock (intptr_ctor_cache) { + if (intptr_ctor_cache.TryGetValue (type, out var rv)) + return rv; + } var ctors = type.GetConstructors (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic); for (int i = 0; i < ctors.Length; ++i) { var param = ctors[i].GetParameters (); - if (param.Length == 1 && param [0].ParameterType == typeof (IntPtr)) + if (param.Length == 1 && param [0].ParameterType == typeof (IntPtr)) { + lock (intptr_ctor_cache) + intptr_ctor_cache [type] = ctors [i]; return ctors [i]; + } } return null; } static ConstructorInfo GetIntPtr_BoolConstructor (Type type) { + lock (intptr_bool_ctor_cache) { + if (intptr_bool_ctor_cache.TryGetValue (type, out var rv)) + return rv; + } var ctors = type.GetConstructors (BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic); for (int i = 0; i < ctors.Length; ++i) { var param = ctors[i].GetParameters (); - if (param.Length == 2 && param [0].ParameterType == typeof (IntPtr) && param [1].ParameterType == typeof (bool)) + if (param.Length == 2 && param [0].ParameterType == typeof (IntPtr) && param [1].ParameterType == typeof (bool)) { + lock (intptr_bool_ctor_cache) + intptr_bool_ctor_cache [type] = ctors [i]; return ctors [i]; + } } return null; }