I was wondering if someone can shed some light on how reflection and also Dynamic LINQ causes a performance hit on 'first time usage' vs 'subsequent usages'.
Below is a snippet of my test case. My intention was to run the query 10 times, each iteration with different input parameters. What I noticed that was the first iteration was always slow with Dynamic LINQ, but faster for subsequent runs.
My question isn't specific to Dynamic LINQ, but Reflection also. Is .Net caching something on first usage? (e.g. dynamic LINQ expression tress, reflection PropertyInfo) What if this was a multi-threaded application? Where/how is this cached? e.g. in some local context? local thread? in global context?
BTW, our front-end is a WebApi app... so I'm wondering if we would be able to make use of performance gains on subsequent web requests?
var sw = new Stopwatch();
for (var i = 1; i <= iterations; i++)
{
//--- Part 1: Setup filter inputs
// code removed for brevity (e.g. startDate, endDate, location, etc.)
//--- Part 2: Regular LINQ
elapsedTime = 0;
RunStandardLinq(sw, startDate, endDate, location, mrnIds, out expected, out elapsedTime);
elapsedTimeRegularLinq += elapsedTime;
//--- Part 3: Dynamic LINQ
elapsedTime = 0;
RunDynamicLinq(sw, startDate, endDate, location, mrnIdsString, out actual, out elapsedTime);
elapsedTimeDynamicLinq += elapsedTime;
}
Here are the LINQ queries
private void RunStandardLinq(Stopwatch sw, DateTime startDate, DateTime endDate, string location, string[] mrnIds,
out IEnumerable<Encounter> results, out double elapsedMilliseconds)
{
//--- Regular LINQ operations - must match the Dynamic LINQ
sw.Restart();
results = _sampleData
.Where(e => e.Admission.Date >= startDate)
.Where(e => e.Admission.Date < endDate)
.Where(e => e.Location == location)
.Where(e => mrnIds.Contains(e.PhnIdentifier.Id))
.OrderByDescending(e => e.PhnIdentifier.Code)
;
List<Encounter> output = results.ToList(); // just to make sure it is executed
sw.Stop();
elapsedMilliseconds = sw.Elapsed.TotalMilliseconds;
}
private void RunDynamicLinq(Stopwatch sw, DateTime startDate, DateTime endDate, string location, string mrnIdsString,
out IEnumerable<Encounter> results, out double elapsedMilliseconds)
{
//--- Dynamic LINQ operations - must match the Regular LINQ
sw.Restart();
IEnumerable resultsEnumerable = DynamicQueryable.OrderBy(_sampleData
.Where(@"Admission.Date >= @0", startDate)
.Where(@"Admission.Date < @0", endDate)
.Where(string.Format(@"Location=""{0}""", location))
.Where(@"PhnIdentifier.Id in " + mrnIdsString),
"PhnIdentifier.Code descending");
List<Encounter> output = resultsEnumerable.Cast<Encounter>().ToList();
sw.Stop();
elapsedMilliseconds = sw.Elapsed.TotalMilliseconds;
results = resultsEnumerable.Cast<Encounter>();
}
Aucun commentaire:
Enregistrer un commentaire