2012-12-07 31 views
0

我在我的WCF REST服務中使用的AutoMapper和StructureMap中使用內存似乎存在內存泄漏。結構圖automapper內存泄漏?

在負載測試中,我可以看到內存使用情況不斷上升,當我使用內存分析器進行更仔細的檢查時,可以看到MappingEngine構建的對象有很多實例(大約是任何其他實例)

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的問題。

代碼樣本...

引導程序(來自的Application_Start在global.asax中稱爲),用於自動地圖...

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

回答

1

看來問題是由MappingEngine的配置引起的 - 它需要設置爲單例,否則實例不會被清除,因爲它是IDisposable。

所以配置改爲..

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