【问题标题】:Performance on Reflection and also Dynamic LINQ - 'first time' vs 'subsequent runs'反射性能和动态 LINQ -“第一次”与“后续运行”
【发布时间】:2015-12-12 03:34:13
【问题描述】:

我想知道是否有人可以阐明反射和动态 LINQ 如何对“首次使用”和“后续使用”造成性能影响。

下面是我的测试用例的 sn-p。 我的意图是运行查询 10 次,每次迭代使用不同的输入参数。我注意到动态 LINQ 的第一次迭代总是很慢,但后续运行更快。

我的问题不是针对动态 LINQ,而是针对反射。 .Net 在第一次使用时会缓存一些东西吗? (例如动态 LINQ 表达式树、反射 PropertyInfo) 如果这是一个多线程应用程序怎么办? 这是在哪里/如何缓存的?例如在某些当地情况下?本地线程?在全球范围内?

顺便说一句,我们的前端是一个 WebApi 应用程序...所以我想知道我们是否能够利用后续 Web 请求的性能提升?

    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;
    }

这是 LINQ 查询

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;
}

【问题讨论】:

  • 这可能是由于sqlserver缓存了查询...
  • 数据在内存中生成。不涉及 sql server 数据库。
  • 您是否尝试过交换标准和动态 LINQ 调用的顺序以查看是否得到相同或不同的结果?

标签: c# performance linq dynamic reflection


【解决方案1】:

见here:

调用站点缓存。动态调用站点是代码中的一个位置,您可以在其中对动态对象执行 a + b 或 a.b() 之类的操作。 DLR 缓存 a 和 b 的特征(通常是这些对象的类型)和有关操作的信息。如果之前已经执行过这样的操作,DLR 会从缓存中检索所有必要的信息以进行快速调度。

【讨论】:

  • 谢谢!我完全错过了 DLR 的介绍,我将不得不阅读它。但快速的问题 - 你知道呼叫站点缓存在哪里吗?即它是否跨线程缓存?
猜你喜欢
  • 2018-05-21
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多