views:

250

answers:

3

Consider a web application that resizes large tiff files on the fly. Each large tiff file is resized into a jpg thumbnail and larger jpg when the user invokes the operation. The dimensions of these converted files is always the same.

During a code review yesterday, one of the other developers asked me why I set those dimensions in my global.asax like so:

    Application["resizedImageWidth"] = int.Parse(ConfigurationManager.AppSettings["ResizedImageWidth"]);

, instead of just looking up the value via a Configuration file during the actual method invocation. I store the widths in the configuration file in the event the end user's after testing the application would like to alter dimensions so I would not have to change code inline.

The reasoning I gave was to prevent the read from the configuration file each time an image was generated, but could not answer if there was similar overhead during a lookup to application level variables. This optimization probably doesn't affect performance to a large scale, but I wanted to know what the community thought the more efficient solution was, i.e. set them during Application start up, or read them on the fly during method invocation.

+2  A: 

Generally you should read from the configuration on the fly as you need it. The framework will cache the configuration file, so it is fairly performant. And I believe (Don't quote me) that ASP.Net can monitor and bring in the changes to a configuration file without restarting the application.

I typically like to create a Configuration class which will hide the details of where the value is stored:

public static class Config
{

   public static int GetXDimension()
   {
      ...
   }

}

This keeps your calling code clean from the configuration code, and if you find I'm wrong, you won't have to change your code everywhere.

JoshBerke
If you extract the settings into a separate config file, then you can indeed change them without restarting the application: For the appSettings section, you use the file attribute (http://msdn.microsoft.com/en-us/library/ms228154.aspx), for other elements you can (where supported) use the configSource element (http://msdn.microsoft.com/en-us/library/ms228167.aspx) in conjunction with the restartOnExternalChanges attribute (http://msdn.microsoft.com/en-us/library/ms228245.aspx) set to false.
Zhaph - Ben Duguid
+1  A: 

You are correct to store this value in an Application object. Indeed, that is the express purpose behind the provision of Application: to hold values that are to be available across all pages and users of the application.

It will indeed be more performant as the application settings are held in memory. It should be pretty obvious that reading from memory is significantly faster than reading from your configuration file (not to mention the lookup via the ConfigurationManager.AppSettings class method and the integer parse).

Any changes to the web.config file will indeed result in a restart of the application. Indeed, this is how I restart my application (when needed) during testing. If you need to change this value "on the fly" you may even want to store this value in a "Configuration" table in your database rather than keeping it in the Web.config file so that changing it doesn't reboot the App.

One trick that I have used is similar to Josh's Config class: I have a "BusinessLogic" class and I place a small handful of settings in static variables of this class so that I can access them in a type-safe manner. It isn't hard and the payoff is pretty obvious in terms of readability.

Mark Brittingham
+1  A: 

I would recommend expanding Josh's answer and call it on demand, but then cache it into a private variable:

public static class Config
{
   private static int? xDimension;
   public static int GetXDimension()
   {
      if(xDimension == null)
          xDimension = int.Parse(ConfigurationManager.AppSettings["ResizedImageWidth"]);
      return xDimension.Value;
   }
}

or into the Application:

public static class Config
{
   public static int GetXDimension()
   {
      if(Application["xDimension"] == null)
          Application["xDimension"] = int.Parse(ConfigurationManager.AppSettings["ResizedImageWidth"]);
      return (int)Application["xDimension"];
   }
}
Chris