前言:我正在移动一个库以并行处理数据,并且线程之间存在 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()
。它返回的PropertyInfo
s 引用了相同的对象,因此即使是在执行缓存。
附加信息/发现:
- 属性 getter 的 MethodInfo 也缓存在
PropertyInfo
. 因此,获取和调用该方法是不可并行的,因为它将依赖于所有线程的相同 MethodInfo 实例。 - ( ) 在使用
PropertyDescriptor
( )ReflectPropertyDescriptor
期间经历的过程,它使用属性信息缓存返回结果。GetValue()
Type.GetProperty()
RunTimeType.GetProperty()
- 这意味着
PropertyDescriptor
并且PropertyInfo
似乎使用相同的共享缓存来返回属性信息实例,它们都用于访问属性 getter 方法(也被缓存)。
- 这意味着
TL;DR:它一直是缓存。