Skip to content

Commit e401cd1

Browse files
Replace an O(n) lookup in LINQ query parsing by an O(1) one
The HQL generators registry already uses dictionaries to resolve generators for methods found in LINQ expression. But some generators do not declare statically their supported methods and instead have to been queried with a loop on them for support of methods encountered in the LINQ query. The result of this lookup can be cached for avoiding calling this loop again on the next query using the method. If nhibernate#1868 is merged, this change will compensate for nhibernate#1868 causing up to three such lookup by method.
1 parent fe440a0 commit e401cd1

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

src/NHibernate/Linq/Functions/DefaultLinqToHqlGeneratorsRegistry.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Concurrent;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Reflection;
45

@@ -10,6 +11,9 @@ public class DefaultLinqToHqlGeneratorsRegistry : ILinqToHqlGeneratorsRegistry
1011
private readonly Dictionary<MemberInfo, IHqlGeneratorForProperty> registeredProperties = new Dictionary<MemberInfo, IHqlGeneratorForProperty>();
1112
private readonly List<IRuntimeMethodHqlGenerator> runtimeMethodHqlGenerators = new List<IRuntimeMethodHqlGenerator>();
1213

14+
private readonly ConcurrentDictionary<MethodInfo, IHqlGeneratorForMethod> _cachedRuntimeMethodHqlGenerators =
15+
new ConcurrentDictionary<MethodInfo, IHqlGeneratorForMethod>();
16+
1317
public DefaultLinqToHqlGeneratorsRegistry()
1418
{
1519
RegisterGenerator(new StandardLinqExtensionMethodGenerator());
@@ -69,14 +73,15 @@ public DefaultLinqToHqlGeneratorsRegistry()
6973

7074
protected bool GetRuntimeMethodGenerator(MethodInfo method, out IHqlGeneratorForMethod methodGenerator)
7175
{
72-
methodGenerator = null;
73-
74-
foreach (var typeGenerator in runtimeMethodHqlGenerators.Where(typeGenerator => typeGenerator.SupportsMethod(method)))
75-
{
76-
methodGenerator = typeGenerator.GetMethodGenerator(method);
77-
return true;
78-
}
79-
return false;
76+
methodGenerator = _cachedRuntimeMethodHqlGenerators.GetOrAdd(
77+
method,
78+
m =>
79+
runtimeMethodHqlGenerators
80+
.Where(g => g.SupportsMethod(m))
81+
.Select(g => g.GetMethodGenerator(m))
82+
.FirstOrDefault());
83+
84+
return methodGenerator != null;
8085
}
8186

8287
public virtual bool TryGetGenerator(MethodInfo method, out IHqlGeneratorForMethod generator)
@@ -112,6 +117,7 @@ public virtual void RegisterGenerator(MemberInfo property, IHqlGeneratorForPrope
112117
public void RegisterGenerator(IRuntimeMethodHqlGenerator generator)
113118
{
114119
runtimeMethodHqlGenerators.Add(generator);
120+
_cachedRuntimeMethodHqlGenerators.Clear();
115121
}
116122
}
117123
}

0 commit comments

Comments
 (0)