gpt4 book ai didi

.net - 有什么方法可以提高 Automapper 的性能吗?

转载 作者:行者123 更新时间:2023-12-03 03:22:39 24 4
gpt4 key购买 nike

我是 AutoMapper 的忠实粉丝。我现在在许多项目中使用它来映射不同域之间的实体,例如从 wcf 服务模型到业务模型。

在示例网站中进行一些负载测试(使用 VS Profiler)后,我发现 AutoMapper 导致了高 CPU 消耗。

我已经为此行为做了一些单元:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace AutoMapper.Tests
{
[TestClass]
public class UnitTest
{
public class ClassSource
{
public string PropertyA { get; set; }
public int PropertyB { get; set; }
public NestedClassSource PropertyC { get; set; }
}

public class NestedClassSource
{
public string PropertyD { get; set; }
public DateTime PropertyE { get; set; }
public List<int> PropertyF { get; set; }
}

public class ClassDestination
{
public string PropertyA { get; set; }
public int PropertyB { get; set; }
public NestedClassDestination PropertyC { get; set; }
}

public class NestedClassDestination
{
public string PropertyD { get; set; }
public DateTime PropertyE { get; set; }
public List<int> PropertyF { get; set; }
}

[TestMethod]
public void MappingPerfTests()
{
Mapper.Initialize(a =>
{
a.CreateMap<ClassSource, ClassDestination>();
a.CreateMap<NestedClassSource, NestedClassDestination>();

});
Mapper.AssertConfigurationIsValid();

IList<ClassSource> items = GenerateRandomSources(nbItems: 500);

//automapper
MicroBench(() =>
{
var res = Mapper.Map<IList<ClassSource>, IList<ClassDestination>>(items);
}, nbIterations: 10);
// will take nearly 30 ms per test
// total : 300 ms


//manual mapper
MicroBench(() =>
{
var res = new List<ClassDestination>(items.Count);
foreach (var source in items)
{
res.Add(new ClassDestination()
{
PropertyA = source.PropertyA,
PropertyB = source.PropertyB,
PropertyC = new NestedClassDestination()
{
PropertyD = source.PropertyC.PropertyD,
PropertyE = source.PropertyC.PropertyE,
PropertyF = new List<int>(source.PropertyC.PropertyF)
}

});
}
}, nbIterations: 10);
// will take nearly 0 ms per test
// total : 1 ms

}

private IList<ClassSource> GenerateRandomSources(int nbItems = 1000)
{
IList<ClassSource> res = new List<ClassSource>(100);
foreach (var i in Enumerable.Range(1, nbItems))
{
ClassSource item = new ClassSource()
{
PropertyA = "PropertyA",
PropertyB = i,
PropertyC = new NestedClassSource() { PropertyD = "PropertyD", PropertyE = DateTime.Now, PropertyF = Enumerable.Range(1, 10).ToList() }
};
res.Add(item);
}
return res;
}

private void MicroBench(Action action, int nbIterations = 1000)
{
long totalElapsed = 0L;

foreach (var i in Enumerable.Range(1, nbIterations))
{
Stopwatch watcher = Stopwatch.StartNew();

action();

watcher.Stop();
Console.WriteLine("test : {0} ms", watcher.ElapsedMilliseconds);
totalElapsed += watcher.ElapsedMilliseconds;
}

Console.WriteLine("total : {0} ms", totalElapsed);
Console.WriteLine("avg : {0} ms", totalElapsed / nbIterations);

}
}
}

最后,AutoMapper 看起来相当慢:每次测试平均需要 30 毫秒,而手动映射只需要不到 1 毫秒。我“仅”映射 500 个“简单”对象!也许对于 MVC ViewModel,这种情况很少发生,但其他映射它的情况可能会很频繁。

30 毫秒看起来很快,但真正的麻烦在于,这 30 毫秒(毫无意义)是Web 服务器上的 CPU 时间 服务器将如何处理重负载(100 个并发用户) ?事实上不太好,这就是我们的负载测试抛出警告的原因。

我找到了一种使用 Mapper.CreateMapExpression 生成 linq 表达式的方法,但不幸的是该表达式不包含嵌套类型或选项。

那么,有没有办法提高AutoMapper的性能呢?有最佳实践吗?

谢谢

最佳答案

阅读本文,深入了解 AutoMapper、其替代方案以及性能指标。我认为这会给你更全面的看法,你不会太关心性能。

Which is faster: AutoMapper, Valuinjector, or manual mapping? To what degree is each one faster?

我的观点是相似的 - 你的问题没有正确的答案(你在帖子中并没有真正提出问题:))。您在 CPU 时间与人类时间(维护)之间进行平衡,并且无法比较两者。但恕我直言,这应该是决定性因素,但显然取决于您采取什么方法。

编辑

尝试在此处查看是否找到与您的情况相关的一些线索:Need to speed up automapper...It takes 32 seconds to do 113 objects

还有另一个链接(虽然是 2009 年的),但也许仍然相关...... Analyzing AutoMapper performance

谢谢,希望这对您有所帮助。

关于.net - 有什么方法可以提高 Automapper 的性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12532129/

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