【问题标题】:How to reduce Enterprise Library 5.0 Logging memory usage?如何减少 Enterprise Library 5.0 Logging 内存使用量?
【发布时间】:2012-02-18 07:15:27
【问题描述】:

我在 .net 4.0 控制台应用程序中使用企业日志记录 5.0。我注意到我的应用程序中的内存使用率非常高。我能够确定原因是由于以下调用:

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

在使用简单的控制台应用程序进行一些分析和手动测试后,我能够确定当从执行文件夹中删除以下 dll 时,内存使用量从 45mb 下降到 10mb

  • 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\Blocks\Common\Src\Configuration\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(Name) 的调用会查看 Executing Assembly 位置,这似乎是它注册 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;
    }

当 dbProviderName=Oracle.DataAccess.Client.OracleClientFactory 时调用 DbProviderFactories.GetFactory(dbProviderName) 会导致巨大的内存峰值。

所以看起来巨大的内存峰值的原因是由于 odp.net 以及它注册 DBFactories 的事实。

如果不注册执行程序集位置中存在的所有内容,我似乎无法创建记录器。理想情况下,除非明确告知,否则我不想注册数据访问权限。

【问题讨论】:

标签: c#-4.0 logging memory-management enterprise-library


【解决方案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);

以及为什么它向容器注册数据访问。

【讨论】:

  • 我要分析 DBProviderFactories.GetFactory("Oracle.DataAccess.Client");了解为什么需要这么多内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 2018-07-12
相关资源
最近更新 更多