2

前言:我正在移动一个库以并行处理数据,并且线程之间存在 85%+ 的争用PropertyDescriptor.GetValue(),这使得多核上的并行处理相同,有时甚至比单核上的处理更糟糕。

问题:

TypeDescriptor.GetProperties(Type)被调用时,它似乎返回对相同的相同引用PropertyDescriptorCollection,它对所有相同的PropertyDescriptor对象具有相同的引用。PropertyDescriptor这是有问题的,因为我需要为每个线程创建新的集合。共享相同的资源会导致线程不断地相互阻塞。

并发分析输出: 在此处输入图像描述

粗略的例子:

    public static void Test()
    {
        var class1 = new ExampleClass();
        var class2 = new ExampleClass();

        var test1 = TypeDescriptor.GetProperties(typeof(ExampleClass));
        var test2 = TypeDescriptor.GetProperties(typeof(ExampleClass));
        Console.WriteLine(Object.ReferenceEquals(test1, test2));
        int i = 0;
        foreach(PropertyDescriptor item in test1)
        {
            Console.WriteLine(Object.ReferenceEquals(test1[i], test2[i]));
            i++;
        }
    }

在这种情况下,每个Object.ReferenceEquals都将返回 true。表明它们都指的是相同的对象,并且没有区别。当多个线程调用GetValue()同一个PropertyDescriptor对象时,这会导致严重的性能问题。

如何PropertyDescriptor为每个对象属性获取全新的对象?


注意:PropertyInfo通过检索也会出现同样的问题myType.GetProperties()。它返回的PropertyInfos 引用了相同的对象,因此即使是在执行缓存。


附加信息/发现:

  • 属性 getter 的 MethodInfo 也缓存在PropertyInfo. 因此,获取和调用该方法是不可并行的,因为它将依赖于所有线程的相同 MethodInfo 实例。
  • ( ) 在使用PropertyDescriptor( )ReflectPropertyDescriptor期间经历的过程,它使用属性信息缓存返回结果。 GetValue()Type.GetProperty()RunTimeType.GetProperty()
    • 这意味着PropertyDescriptor并且PropertyInfo似乎使用相同的共享缓存来返回属性信息实例,它们都用于访问属性 getter 方法(也被缓存)。

TL;DR:它一直是缓存。

4

0 回答 0