简体   繁体   中英

Performance on Reflection and also Dynamic LINQ - 'first time' vs 'subsequent runs'

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? (eg dynamic LINQ expression tress, reflection PropertyInfo) What if this was a multi-threaded application? Where/how is this cached? eg 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();
    var resultsEnumerable = _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)
                   ;
    results = resultsEnumerable.ToList();
    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");

    results = resultsEnumerable.Cast<Encounter>().ToList(); 
    sw.Stop();
    elapsedMilliseconds = sw.Elapsed.TotalMilliseconds;
}

See here :

Call site caching. A dynamic call site is a place in the code where you perform an operation like a + b or ab() on dynamic objects. The DLR caches the characteristics of a and b (usually the types of these objects) and information about the operation. If such an operation has been performed previously, the DLR retrieves all the necessary information from the cache for fast dispatch.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM