structuremap automapper内存泄漏?

时间:2012-12-07 14:14:22

标签: c# wcf memory-leaks automapper structuremap

在我的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

(抱歉垃圾格式,但我不会让我发布图片)

问题是我不确定我的代码,StructureMap或AutoMapper是否存在问题。

代码示例......

Bootstrapper(从global.asax中的Application_Start调用)for automap ...

    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休息服务使用...

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;     
        }
}

1 个答案:

答案 0 :(得分:1)

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

所以配置改为..

For<IMappingEngine>().Singleton().Use<MappingEngine>();