gpt4 book ai didi

c# - 如何使用声明方式而不是 LINQ-to-Objects 来提高性能?

转载 作者:行者123 更新时间:2023-11-30 15:22:16 25 4
gpt4 key购买 nike

让我们看看 LINQ-to-Objects。此代码引入了多少低效率?

public object GetObjectToSerialize(object value, Type targetType)
{
var type = value.GetType();
PropertyInfo[] setToNullProperties;

if (!_typeToPropertyMap.TryGetValue(type, out setToNullProperties))
{
var allPropeties = type.GetProperties();
var passwordProperties = allPropeties
.Where(p => p.PropertyType == typeof(string))
.Where(p => p.Name.Contains("Password")).ToArray();

var passwordWithoutEncryptedAttribute = passwordProperties
.Where(p => !p.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any());

if (passwordWithoutEncryptedAttribute.Any())
{
throw new InvalidOperationException();
}

var propertiesWithEncryptedAttribute = allPropeties.Where(p => p.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any());
setToNullProperties = passwordProperties.Union(propertiesWithEncryptedAttribute).ToArray();

_typeToPropertyMap[type] = setToNullProperties;
}

foreach (var property in setToNullProperties)
{
property.SetValue(value, null, null);
}

return value;
}

我想知道关于许多 .Where .toArray .Union.

例如,ToArray 方法不知道输出的大小,因此它必须进行多次分配。如果我们有 int 数组而不是 PropertyInfo,它将以 4 个元素开始,然后根据需要不断加倍和复制元素。我们最终可能会拥有过多的存储空间。例如,如果我们最终得到 33,000 元素,我们将浪费大约 128KB 的动态存储空间(32,000 X 4 字节整数)。

此外,当我找到 passwordProperties 时,有两个委托(delegate)对象分配,两个用于调用 Enumerable.Where。这些委托(delegate)可能指向两个不同的闭包对象,每个闭包对象都捕获了封闭变量。这些闭包对象是新类的实例,它们在二进制文件和运行时都占据着重要的空间。 (当然,参数现在存储在两个地方,必须复制到闭包对象,然后我们每次访问它们时都必须进行额外的间接访问。)很可能,Where 运算符将分配新的 IEnumerable 对象。

我如何使用声明方式改进代码(因为随着编译器和运行时享受新的优化,它会变得更快)?

最佳答案

if 中的代码对每种类型执行一次。我看不出有什么问题。即使它比必要的慢 2 倍,它仍然足够快,并且很少执行(免责声明:我写了那段代码:-))

但是你问了如何加速代码......你可以删除几乎所有的 LINQ:

public object GetObjectToSerialize(object value, Type targetType) 
{
var type = value.GetType();
PropertyInfo[] setToNullProperties;

if (!_typeToPropertyMap.TryGetValue(type, out setToNullProperties))
{
PropertyInfo[] allProperties = type.GetProperties();

var setToNullProperties2 = new List<PropertyInfo>(allProperties);

foreach (PropertyInfo property in allProperties)
{
bool isEncrypted = property.GetCustomAttributes(typeof(EncryptedConfigurationItemAttribute), false).Any();
bool isPasswordProperty = false;

if (!isEncrypted)
{
isPasswordProperty = property.PropertyType == typeof(string) && property.Name.Contains("Password");

if (isPasswordProperty) {
throw new InvalidOperationException();
}
}

if (isEncrypted || isPasswordProperty) {
setToNullProperties2.Add(property);
}
}

_typeToPropertyMap[type] = setToNullProperties = setToNullProperties2.ToArray();
}

foreach (var property in setToNullProperties)
{
property.SetValue(value, null, null);
}

return value;
}

真正的加速将是转换 Expression 树生成器中的代码,因此您将删除重复的反射(SetValue 部分)。问题是生成 Expression 树并编译它非常慢,所以除非你对同一个 Type 使用数百次 GetObjectToSerialize 然后你不会有加速。

关于c# - 如何使用声明方式而不是 LINQ-to-Objects 来提高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35989380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com