2012-01-25 89 views
1

我在.net 4.0控制檯應用程序中使用企業日誌記錄5.0。我注意到我的應用程序內存使用率非常高。我能確定,原因是由於以下電話:如何減少Enterprise Library 5.0記錄內存使用情況?

var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>(); 

一些剖析和手動測試用一個簡單的控制檯應用程序後,我能夠確定從45MB內存使用率下降至10MB時下列DLL從該執行文件夾中刪除:

  • Microsoft.Practices.EnterpriseLibrary.Validation.dll
  • Microsoft.Practices.EnterpriseLibrary.Data.dll

日誌初始化是我第一次調用企業庫API。我的控制檯應用程序不會調用Data.dll和Validation.dll。它們存在於我的執行文件夾中,因爲它們是其他類庫的參考和我們的部署設置。

我假設EnterpriseLibraryContainer.Current正在基於在執行文件夾中找到的內容進行初始化。我試圖創建我寫進程具有以下,但我得到了相同的結果:

var configSource = new FileConfigurationSource(configPath);   
var logWriterFactory = new LogWriterFactory(configSource); 
var logWriter = logWriterFactory.Create(); 

是否可以初始化一個寫進程,而不與驗證和數據增加了內存使用的DLL存在於執行文件夾?

更新: 因此,在entlib源內的一些調試。我相信以下是找到DLL並實例化Validation.dll和Data.dll,儘管在項目中根本沒有被引用。

從EntLib50Src \塊\ COMMON \ SRC \配置\ ContainerModel \ TypeLoadingLocator.cs

private IEnumerable<TypeRegistration> GetRegistrationsInternal(IConfigurationSource configurationSource, 
     Func<ITypeRegistrationsProvider, IConfigurationSource, IEnumerable<TypeRegistration>> registrationAccessor) 
    { 
     Type providerType = Type.GetType(Name); 
     if (providerType == null) return new TypeRegistration[0]; 

     var provider = (ITypeRegistrationsProvider)Activator.CreateInstance(providerType); 
     return registrationAccessor(provider, configurationSource); 
    } 

調用Type.GetType(名稱)看在執行程序集的位置,這似乎是它註冊entlib數據訪問的原因。

調試進一步我的原始應用程序,其中包含連接字符串與Oracle ODP.net供應商。 (我從一開始就沒有提到)

(我當前的應用程序執行不會調用或引用數據訪問,因爲應用程序使用對需要連接字符串的其他dll的動態調用來定義連接字符串。但對於我的測試我沒有調用任何這些調用)

由於找到了Microsoft.Practices.EnterpriseLibrary.Data.dll,因此EnterpriseLibrary繼續爲數據訪問類型默認註冊,並且我發現以下調用是造成巨大內存高峯的原因:

\ EntLib50Src \ Blocks \ Data \ Src \ Data \ Configuration \ DatabaseSyntheticConfigSettings.cs

private static DbProviderMapping GetDefaultMapping(string dbProviderName) 
    { 
     // try to short circuit by default name 
     if (DbProviderMapping.DefaultSqlProviderName.Equals(dbProviderName)) 
      return defaultSqlMapping; 

     if (DbProviderMapping.DefaultOracleProviderName.Equals(dbProviderName)) 
      return defaultOracleMapping; 

     // get the default based on type 
     var providerFactory = DbProviderFactories.GetFactory(dbProviderName); 


     if (SqlClientFactory.Instance == providerFactory) 
      return defaultSqlMapping; 

     if (OracleClientFactory.Instance == providerFactory) 
      return defaultOracleMapping; 

     return null; 
    } 

的DbProviderFactories.GetFactory(dbProviderName)調用時dbProviderName = Oracle.DataAccess。Client.OracleClientFactory導致巨大的內存峯值。

所以看起來像是由於odp.net和其註冊DBFactories的事實導致的巨大內存高峯的原因。

看來我不能創建一個記錄器,而無需註冊執行裝配位置中的所有內容。理想情況下,除非明確告知,否則我不想註冊數據訪問。

+0

也在這裏創建了一個討論: http://entlib.codeplex.com/discussions/287422 –

回答

1

ODP.NET被用作底層提供者的事實是內存高峯的主要原因,並且GetDefaultMapping無論如何都會返回null。下面的變化可以作出:

private static DbProviderMapping GetDefaultMapping(string dbProviderName) 
    { 
     // try to short circuit by default name 
     if (DbProviderMapping.DefaultSqlProviderName.Equals(dbProviderName)) 
      return defaultSqlMapping; 

     if (DbProviderMapping.DefaultOracleProviderName.Equals(dbProviderName)) 
      return defaultOracleMapping; 


     if (dbProviderName != "Oracle.DataAccess.Client") 
     { 
      // get the default based on type 
      var providerFactory = DbProviderFactories.GetFactory(dbProviderName); 


      if (SqlClientFactory.Instance == providerFactory) 
       return defaultSqlMapping; 

      if (OracleClientFactory.Instance == providerFactory) 
       return defaultOracleMapping; 
     } 

     return null; 
    } 

這仍然沒有解釋爲什麼Oracle.DataAccess.Client使用這麼多的內存爲:

DbProviderFactories.GetFactory(dbProviderName);

,以及爲什麼它的登記數據訪問與容器。

+0

我將要剖析DBProviderFactories.GetFactory(「Oracle.DataAccess.Client」);瞭解爲什麼需要這麼多的記憶 –

相關問題