在我的 WCF REST 服务中使用的 AutoMapper 和 StructureMap 的使用中似乎存在内存泄漏。
在负载测试下,我可以看到内存使用量不断上升,当我使用内存分析器更仔细地检查它时,我可以看到 MappingEngine 使用的对象有很多实例(大约是任何其他实例的 9 倍)
Class Name=Live Instances
Object=498,847
Int32[]=69,373
Object[]=68,116
ConcurrentDictionary<TKey, TValue>+Node<TypePair, IObjectMapper>=37,624
string=35,240
IObjectMapper[]=30,782
EventHandler<TypeMapCreatedEventArgs>=30,782
MappingEngine=30,781
ConcurrentDictionary<TypePair, IObjectMapper>=30,781
ConcurrentDictionary<TKey, TValue>+Node<TypePair, LambdaExpression>[]=30,781
ConcurrentDictionary<TKey, TValue>+Node<TypePair, IObjectMapper>[]=30,781
ConcurrentDictionary<TypePair, LambdaExpression>=30,781
这是一个典型的实例保留图......
bootstrapper._configuration
-> AutoMapper.ConfigurationStore (TypeMapCreated)
-> System.EventHandler<TypeMapCreatedEventArgs> (multicast delegate)
-> System.Object[]
-> System.EventHandler<TypeMapCreatedEventArgs>
-> AutoMapper.MappingEngine (_objectMapperCache)
-> System.Collections.Concurrent.ConcurrentDictionary<Internal.typePair, IObjectMapper> (m_locks)
-> System.Object[]
-> System.Object
(对不起垃圾格式,但SO不会让我发布图片)
问题是我不确定我的代码、StructureMap 还是 AutoMapper 是否有问题。
代码示例...
用于自动映射的引导程序(从 global.asax 中的 Application_Start 调用)...
public class BootStrapper
{
private static readonly IConfiguration _configuration = ObjectFactory.GetInstance<IConfiguration>();
public static void Initialize()
{
_configuration.AddProfile<AutoMapperProfile>();
}
public class AutoMapperProfile : Profile
{
protected override void Configure()
{
BootstrapAutoMapper();
}
}
public static void BootstrapAutoMapper()
{
_configuration.CreateMap<In.Account, Out.Accounts.Account>()
.ForMember(m => m.AccountNumber, o => o.MapFrom(s => s.AcctId))
.ForMember(m => m.Balances, o => o.Ignore())
.ForMember(m => m.AccountTypeDescription, o => o.MapFrom(s => s.TypeName))
.ForMember(m => m.AccountType, o => o.MapFrom(s => s.Type))
.ForMember(m => m.IsNoticeAccount, o => o.ResolveUsing(s => IsNoticeAccountMapper.Map(s.Type, ObjectFactory.GetInstance<IAccountTypeHelper>())));
// many other mappings excluded for brevity
}
}
它在 StructureMap 中配置...
private void AutoMapperRegistration()
{
For<ConfigurationStore>().Singleton().Use<ConfigurationStore>().Ctor<IEnumerable<IObjectMapper>>().Is(AutoMapper.Mappers.MapperRegistry.AllMappers());
For<IConfigurationProvider>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
For<IConfiguration>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
For<ITypeMapFactory>().Use<TypeMapFactory>();
For<IMappingEngine>().Use<MappingEngine>();
Scan(scan =>
{
scan.AssemblyContainingType<AppRegistry>();
scan.AddAllTypesOf<Profile>();
});
}
典型的 WCF Rest 服务使用...
public class AccountService : IAccountService
{
private readonly IMappingEngine _mappingEngine;
private readonly IAccountFacade _accountFacade;
public AccountService(IMappingEngine mappingEngine, IAccountFacade accountFacade)
{
_mappingEngine = mappingEngine;
_accountFacade = accountFacade;
}
public IEnumerable<Account> GetAccounts()
{
var ret = new List<Account>();
var entities = _accountFacade.GetAccounts().ToList();
foreach (var account in entities.Select(entity => _mappingEngine.Map<In.Account, Out.Account>(entity)))
{
ret.Add(account);
}
return ret;
}
}