简体   繁体   English

.NET 反射在 .NET 4.7.x 中比在 3.5 中慢 3 倍

[英].NET reflection 3 times slower in .NET 4.7.x than in 3.5

I have an application that we upgraded form .NET 3.5 to .NET 4.7.2.我有一个从 .NET 3.5 升级到 .NET 4.7.2 的应用程序。 The only problem really is performance from part of our code that uses reflection.唯一的问题确实是我们使用反射的部分代码的性能。 Entire situation is best explained in a simple sample I uploaded to Gist: https://gist.github.com/vkocjancic/3e8a6b3496c412a75b1c85a1d2ba1111整个情况在我上传到 Gist 的一个简单示例中得到了最好的解释: https ://gist.github.com/vkocjancic/3e8a6b3496c412a75b1c85a1d2ba1111

Basically, we have a POCO class, which property methods throw exceptions, if value is not set for properties of non-nullable types.基本上,我们有一个 POCO 类,如果未为不可空类型的属性设置值,则属性方法会抛出异常。

[EDIT]: [编辑]:

  1. Yes, I know that is not correct or a good pattern to use, but, the application started in .NET 1.1.是的,我知道那是不正确的或不适合使用的模式,但是,该应用程序是从 .NET 1.1 开始的。

  2. Yes, it should have been fixed long ago.是的,它早就应该修好了。 It wasn't.事实并非如此。

A reflection is then used to get property names and values of instances of POCO class and popluate it to DataTable.然后使用反射获取 POCO 类实例的属性名称和值,并将其填充到 DataTable。

The sample and real life project source code is exactly the same.示例和现实生活中的项目源代码完全相同。 The only difference is that in one case it is compiled using .NET 3.5 and in second using .NET 4.7.2.唯一的区别是,在一种情况下,它是使用 .NET 3.5 编译的,而在第二种情况下,它是使用 .NET 4.7.2 编译的。

This is the average time elapsed in milliseconds for 10 invocations:这是 10 次调用的平均耗时(以毫秒为单位):

.NET 3.5      ->  231.1 ms
.NET 4.7.2    ->  713.5 ms
.NET Core 2.2 -> 1013.2 ms

Can anyone elaborate why reflection is about 3 times slower in .NET 4.7.2 than in .NET 3.5 and how to fix that.谁能详细说明为什么反射在 .NET 4.7.2 中比在 .NET 3.5 中慢 3 倍,以及如何解决这个问题。 The lag only happens, when properties are not set and throw exceptions.只有在未设置属性并抛出异常时才会发生滞后。 If you populate property values, there is no difference in performance.如果您填充属性值,则性能没有差异。

If I run sample in debugger, .NET 3.5 build never triggers MissingFieldException.如果我在调试器中运行示例,.NET 3.5 构建永远不会触发 MissingFieldException。 Build using .NET 4.7.2 triggers every exception.使用 .NET 4.7.2 构建会触发每个异常。

[EDIT] [编辑]

As @bevan mentioned, the slowdown actually occurs when switching to .NET 4.0.正如@bevan 所提到的,减速实际上发生在切换到 .NET 4.0 时。 > Also the problem boils down to exception being thrown and handled 3 times faster in .NET 3.5 than it is in .NET 4.0 > 此外,问题归结为在 .NET 3.5 中抛出和处理异常的速度比在 .NET 4.0 中快 3 倍

As i mentioned in the comments, if you call the IsPROP_NUMERIC_ANull function before you access the properties, it wont throw any more exceptions and is super fast.正如我在评论中提到的,如果您在访问属性之前调用IsPROP_NUMERIC_ANull函数,它不会再抛出任何异常并且速度非常快。

foreach (var myObject in objects)
{
    var row = table.NewRow();

    // TODO implement some caching: dont call GetProperties(), GetMethod(), for every object
    var type = myObject.GetType();
    var properties = type.GetProperties();

    foreach (var info in properties)
    {
        try
        {
            // call the IsNullMethod for the property, eg "IsPROP_NUMERIC_ANull"
            var isNullMethodName = $"Is{info.Name}Null";
            var isNullMethod = type.GetMethod(isNullMethodName, BindingFlags.Instance | BindingFlags.Public);

            if (isNullMethod != null)
            {
                var fldIsNull = (bool)isNullMethod.Invoke(myObject, new object[] { });
                if (!fldIsNull)
                    row[info.Name] = info.GetValue(myObject, null);
            } else
            {
                // isNullMethod doesn't exist
                row[info.Name] = info.GetValue(myObject, null);
            }
        }
        catch
        {
            // do nothing
        }
    }
    table.Rows.Add(row);
}

Total runtime is 3 ms vs 19500 ms you had before.总运行时间为3 ms ,而之前为 19500 毫秒。

If you can redesign this i would use Cached Delegates like Marc Gravell proposed .如果您可以重新设计它,我会使用像 Marc Gravell 提议的缓存委托。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 .NET 4.7.x不会显示主窗口/ WPF升级到.NET到4.7.x可能导致无限循环 - Main window does not display with .NET 4.7.x / WPF upgrade to .NET to 4.7.x can result in infinite loops 将项目从.Net 4.6.1升级到4.7.x会导致WCF Reference.cs中出现错误 - Upgrading projects from .Net 4.6.1 to 4.7.x causes errors in WCF Reference.cs Microsoft.AspNetCore.Identity.EntityFrameworkCore 3.1.2 是否对 .NET 4.7.x 项目有效? - Is Microsoft.AspNetCore.Identity.EntityFrameworkCore 3.1.2 valid for .NET 4.7.x projects? .Net Framework 3.5反射问题 - .Net Framework 3.5 reflection issues Selenium geckodriver 执行 findElement 比 chromedriver (.Net) 慢 10 倍 - Selenium geckodriver executes findElement 10 times slower than chromedriver (.Net) 在 .NET 3.5 中生成带有反射的子类列表 - Generating a list of child classes with reflection in .NET 3.5 ASP.NET Web API 2中的并发请求比单个请求慢近六倍 - Concurrent request in ASP.NET Web API 2 is nearly six times slower than a single request 是什么原因导致GetHashCode的实现比.net的实现慢20倍? - What is causing this implementation of GetHashCode to be 20 times slower than .net's implementation? .NET Core 2.1 - 循环中的正则表达式200x比2.0慢(简单基准中为3x) - .NET Core 2.1 - Regex in loop 200x slower than 2.0 (3x in simple benchmark) .Net Release构建比Debug慢 - .Net Release build working slower than Debug
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM