读取app.config文件是否耗费资源?

31

我还没有遇到读取速度受阻的问题。我想知道的是:频繁读取 app.config 是否是不良编程选择。我知道数据库操作会变得昂贵。

在我的情况下,我并不是在读取自己应用程序的 app.config,而是另一个项目的 app.config,就像这样:

private string GetAppConfigValue(string key)
{
    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    fileMap.ExeConfigFilename = GetConfigFilePath();
    Configuration appConfig = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
    return appConfig.AppSettings.Settings[key].Value;
}

场景:我有一个管理类(且只有一个这样的类),需要从一个指定的物理路径的配置文件中读取几个值(3到4个),但要进行多次读取。我需要使用一些成员变量来存储来自app.config文件的这些值吗?最好的方法是什么?谢谢。


1
你可以将 appConfig 缓存为静态值,这样你只需要读取一次 app.config。 - jrummell
@jrummell,没错。我的问题是,这样做是正确的方式吗?会有性能损失吗?等等。 - nawfal
远程 app.config 的网络连接质量如何? - Polyfun
@ShellShock,哈哈,它在同一台机器上 :) - nawfal
1
@nawfal。由于这是基于XML的文档,框架内部解析文档肯定会影响性能。值得一提的是,在最新的.NET框架中,所有配置文件都是基于JSON而不是XML的。 - Gowtham
使用ConfigurationManager读取应用程序配置将合并机器配置,这将导致性能下降(尽管我相信这将在第一次访问后被缓存)。如果您知道配置在文件中,则可以编写自己的代码使用XmlDocument和XPath读取配置文件。 - Adam
5个回答

21

我确信所有配置文件(web.config或app.config)默认都被缓存,因此您无需创建一个持有所有值的静态类或担心文件会被永久访问。

以下是一些阅读材料:

关于您需要访问另一个应用程序的配置文件:

MSDN: "这些方法 (注意:对于客户端应用程序:ConfigurationManager.GetSection) 提供对当前应用程序缓存的配置值的访问,具有比 Configuration 类更好的性能。"

换句话说:当它不是您自己的应用程序配置文件时,您应该将其缓存


1
在我的情况下,app.config不属于同一个项目,而是属于另一个项目。你能就这个方面给出一些看法吗?我在问题中提到了这一点。 - nawfal
1
@nawfal: MSDN说:“这些方法(对于客户端应用程序:ConfigurationManager.GetSection)提供了访问当前应用程序的缓存配置值的方式,这比 Configuration 类具有更好的性能。”换句话说:你是正确的,当它不是你自己的应用程序配置文件时,你应该将其缓存。(已相应地编辑我的答案) - Tim Schmelter
MSDN关于应用程序配置文件被缓存的评论并不意味着非应用程序配置文件不会被缓存。我已经进行了测试,打开了一个非应用程序配置文件,在程序外部进行修改并重新打开它。第二次打开文件时没有捕获到我的更改。 - Adam

6

任何以磁盘IO结束的操作都是昂贵的(特别是涉及旋转媒体时)。

请查看Quora上的Jeff Dean认为每个计算机工程师都应该了解的数字,以查看速度差异。

如果您重复读取文件,则应缓存结果(特别是文件不会更改时)。

当使用默认配置时,.config文件仅在应用程序启动时读取一次,并将结果缓存在内存中。


更新,按要求示例:

private Configuration appConfig;

private Configuration GetConfig()
{
    if (appConfig != null)
        return appConfig;

    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    fileMap.ExeConfigFilename = GetConfigFilePath();
    appConfig = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

    return appConfig;
}

假设这段代码存在于一个应用程序生命周期内的类中,你现在已经将配置信息缓存到了应用程序生命周期内的内存中。

Oded,有特定的缓存实现吗?还是只需分配给静态变量即可? - nawfal
@nawfal - 你可以将整个“Config”对象缓存起来。 - Oded
@Oded,能否请您提供一个关于对象缓存的小例子。谢谢。 - Zaki
如果您反复读取磁盘文件,操作系统会为您进行缓存,这是肯定的吧? - Martin Thompson
@oded:好的,我来重新表述一下:在证明操作系统无法满足你的性能目标之前,请让它自行缓存。否则,你可能会浪费本可以更好地利用的内存。过早优化等等 :) - Martin Thompson
1
@MartinThompson - 可能是这样,但配置文件往往占用的内存很少,如果您经常引用它,那么直接使用它是有意义的。我同意在优化之前应该进行测量,但这是一件非常简单且易于正确处理的事情... - Oded

3

在这里,你并不是真正进行输入/输出操作,至少不是直接地。

只需假设 Config 系统将缓存这些值,并且只有在出现性能问题时才采取行动。

用 DIY 缓存随处可见并不值得。


在我的情况下,app.config不属于同一个项目,而是属于另一个项目。你能就这方面给出一些看法吗? - nawfal
1
嗯,是的,我错过了那个。也许保留appConfig是明智的,但这真的取决于您进行多少调用以及需要的范围。 - H H

2

从app.config中读取配置只会在第一次执行应用程序时发生。之后,它将在内存中存储此配置,并在需要访问时从中读取。这就是为什么更改app.config不会影响当前正在运行的应用程序。


2

虽然来自app.config的值正在被缓存,但在多线程场景中频繁读取它们可能会导致严重的性能问题。如果您必须同时访问配置值,则最好使用您自己的缓存。您可以从AppSettingsBase类派生一个自定义实现。

一般来说,在大多数情况下,将默认的配置管理器包装成自己的实现是一个很好的设计决策。这不仅可以使您免受更改(客户?)配置设置名称的影响,还可以为您提供灵活性,以缓存这些值或从任何其他可能/重要的源获取它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接