1

在我的 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;     
        }
}
4

1 回答 1

1

似乎问题是由 MappingEngine 的配置引起的 - 它需要设置为单例,否则实例不会被清除,因为它是 IDisposable。

所以配置更改为..

For<IMappingEngine>().Singleton().Use<MappingEngine>();
于 2012-12-17T09:57:57.160 回答