I don’t claim to be the best developer on the planet
but I’m always amazed at how all the “experts” come out of the woodwork to posh on other peoples code
Several folks have commented and emailed about hey the technique I posted earlier was unnecessary. But only ONE guy (thanks Henrik Juhlin) took the time to research before commenting.
Since the last company that I built did nothing but performance work, it did get me thinking, so I built a little test.
I used 4 potential access methods and ran the test with debugging OFF!
Here are the results.
Retrieve and Assign 200,000 Times
From Application Object : 1797 Milliseconds
From Config File : 1699 Milliseconds
From Resource File : 684 Milliseconds
From Static Variable : 5 Milliseconds
In a real production environment there are, of course, additional factors to consider, but from a pure retrieval perspective, that makes the Static Instance property like 340 TIMES faster than reading from the config file.
Here is the code.
1: static public string MySiteName { get; set; }
2:
3: protected void Page_Load(object sender, EventArgs e)
4: {
5: Application["SiteName"] = "This is s Test";
6: MySiteName = WebConfigurationManager.AppSettings.Get("SiteName");
7:
8:
9: }
10:
11: protected void Button1_Click(object sender, EventArgs e)
12: {
13:
14: string MyString = "This is a string test ";
15: long StartTime;
16: long EndTime;
17: long ElapsedTime;
18:
19: // App Setting
20: StartTime = DateTime.Now.Ticks;
21: for (long i = 0; i < 2000000; i++)
22: {
23: MyString = WebConfigurationManager.AppSettings.Get("SiteName");
24: }
25: EndTime = DateTime.Now.Ticks;
26: ElapsedTime = EndTime - StartTime;
27: ElapsedTime = ElapsedTime / 10000;
28: Label1.Text = ElapsedTime.ToString();
29:
30: // Resource File
31: StartTime = DateTime.Now.Ticks;
32: for (long i = 0; i < 2000000; i++)
33: {
34: MyString = GetLocalResourceObject("Resource1.Text").ToString();
35: }
36: EndTime = DateTime.Now.Ticks;
37: ElapsedTime = EndTime - StartTime;
38: ElapsedTime = ElapsedTime / 10000;
39: Label2.Text = ElapsedTime.ToString();
40:
41: // Application Object
42: StartTime = DateTime.Now.Ticks;
43: for (long i = 0; i < 2000000; i++)
44: {
45: MyString = Application["SiteName"].ToString();
46: }
47: EndTime = DateTime.Now.Ticks;
48: ElapsedTime = EndTime - StartTime;
49: ElapsedTime = ElapsedTime / 10000;
50: Label3.Text = ElapsedTime.ToString();
51:
52: // Static Variable
53: StartTime = DateTime.Now.Ticks;
54: for (long i = 0; i < 2000000; i++)
55: {
56: MyString = MySiteName;
57: }
58: EndTime = DateTime.Now.Ticks;
59: ElapsedTime = EndTime - StartTime;
60: ElapsedTime = ElapsedTime / 10000;
61: Label4.Text = ElapsedTime.ToString();
62: }





















Nice post. I never really thought about how long it takes to access properties, and I’m amazed at how much faster static strings are compared to a web.config entry, seeing as I’d have thought the value would get cached and then used the same as a static value anyway.
Quick note though: in the article you mention it’s for 200,000 retrievals and assignments, but you’re actually timing 2,000,000. (Unless I’m missing something
)
You’re right – I missed a 0
Ha! I knew there was a good reason why I liked static properties.
Thank you for the validation
Now hang on just a second here. I haven’t tested this, but I think you should try it, but you aren’t doing a fair comparison here. Surely calling the .ToString() method takes extra time compared to directly accessing a string static variable. Can you try the same code using a cast instead of .ToString()? I think that would be more fair.
Joe,
As an employee of Microsoft, could you find out why the existing method is slower? I generally hate it when someone tries
to "reinvent" something that is already available.
Sure, your method is faster according to the tests performed. But why is the built in method slower?
Is the web.config indeed being accessed every time? As someone posted, the MSDN docs states that it is cached.
We have several applications that use the default way of accessing properties. Should we start looking at changing all those methods to what you have? Are there any downsides to your method?
Thanks.
The web.config is cached and not accessed multiple time as you stated in your previous post. What makes it slow is the NameValueCollection lookups according to this article (http://dotnetperls.com/cache-settings-aspnet). Sam has also posted a link to a "class from config" generator (http://sourceforge.net/projects/classfromconfig/)
Regards,
Raj
>I’m always amazed at how all the “experts” come out of the
>woodwork to posh on other peoples code
What happened to "Lets build an Application Together."?
Shouldn’t we work as a team and handle criticism with grace
As a team member, it is my opinion that we keep it simple and go with the approach of fetching the values directly. Keeping up with an additional set of static properties is not worth the perf improvement gained.
Raj, It was not being cached in my orrigional tests as I was running in debug mode. Thansk for the link
Tim – the same method is used in the tests – but why don’y you run the tests the way you want and share the results with us.
Joe, I agree with you that using a static variable is obviously faster, and you’ve proved it here. There’s no arguing that, and I applaud you for pointing this out.
That said, I really think you need to clear up the a BIG misconception that you stated from your previous post. Though I’m sure it was not your intention, you have left a lot of newbie developers with a mistaken impression regarding web.config and how it actually works.
The fact is that the AppSettings object *is* cached (as is ConnectionStrings, by the way). That is extremely clear from MS’s own documentation. That means the web.config file is NOT being hit over and over, as you stated in your previous post. Think about it… if we were really doing a million disk I/O operations here, we’d be talking *minutes*, not milliseconds.
The reason your tests show that accessing AppSettings is slower than using a static variable is because AppSettings is a NameValueCollection, and NVC lookups are not very fast.
I guess the bottom line is that your results are correct, but the reasoning behind them is not.
Also, I’d point out that AppSettings is cached whether running in debug mode or not.
You’re correct – the actual DISK file is not read off disk for each read.
From all the replies it is pretty much clear that the difference in numbers is in processing time taken from IL level and not in IO or something. The diff is because of the fact that collection iteration would take more time comparatively than reading a memory location data and assigning it to other location i.e. static variable case.
However if at all we don’t want to go with collection iteration, the best approach would be to use Singleton pattern. This suits best here. You will have better manageability cum better performance – buy one get one free!
What do you say?
How about adding ‘convenient’ methods like below?
These methods can then be used in the static constructor, having all default (non-default) values in one place, as well as the checking for missing configuration values.
static private T Read<T>(string setting, Converter<string, T> converter)
{
var value = ConfigurationManager.AppSettings[setting];
if (value == null) throw new ConfigurationErrorsException(string.Format("AppSettings:{0} is not configured.", setting));
try
{
return converter(value);
}
catch (Exception x)
{
throw new ConfigurationErrorsException(string.Format("AppSettings:{0} is not configured. Cannot convert:{1}", setting, value), x);
}
}
and
static private T Read<T>(string setting, T defaultValue, Converter<string, T> convert) { … }
static int ReadInt32(string setting){ return Read<int>(setting, Convert.ToInt32); }
static int ReadInt32(string setting, int defaultValue) { … }
static bool ReadBoolean(string setting){ return Read<bool>(setting, Convert.ToBoolean); }
bool ReadBoolean(string setting, bool defaultValue) { … }
string ReadString(string setting){ return Read<string>(setting, Convert.ToString); }
bool ReadString(string setting, string defaultValue) { … }
// Ryan
ugh, don’t know why people so amazed – reading variable was always much faster than going into library calls…
i would like to make couple of notes on that:
1. if you measure performance – you must keep in mind that CLR will compile MSIL code into x86 (or whatever CPU you have) on first call. So, when you call GetLocalResourceObject() for the first time in loop – it will add some CLR processing time.
2. it is not correct to say that "static public string MySiteName { get; set; }" is a variable, it’s a property and each time you query it you calling a getter method. You can actually double performance by using real variable, not an autoproperty. You can try this:
using System;
using System.Diagnostics;
namespace ConsoleApplication2
{
class Program
{
static public string MySiteName { get; set; }
static public string MySiteNameVariable;
static void Main(string[] args)
{
MySiteName = "baloklasd";
MySiteNameVariable = "abloklasd";
string s;
var sw = Stopwatch.StartNew();
for (int i = 0; i < 2000000; i++)
{
s = MySiteName;
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw = Stopwatch.StartNew();
for (int i = 0; i < 2000000; i++)
{
s = MySiteNameVariable;
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
}
}
Cheers,
SG
This is interesting but not really suprising. However, I would like to point out a few things. The app/web.config functionality is provided as a standard and convienient way of handling application configuration, not as a high performance data retrieval layer.
You can cache all of your config values in static properties, but by adding this layer of redirections you are loosing a little bit of what the config layer provides. For example, at a later time you might wish to have your app automaticly load the updated config if the config file changes.
most of the time you don’t need to read and re-read your config data over and over and most of the time your config data doesn’t have to high performance.
as a side note, I never stick anything in appSettings. I always create a custome config section. It provides for a richer set config items including lists, defaults and gives a strongly typed method of reading your config data. And once you learn how to do it, its pretty easy.
I just noticed from your linked article that you are specificly interested in a web applicaiton and you are interested in reading some properties very frequently (like page/application title).
Here are some items to consider.
create a custom config section.
in the config section class, you can cache the actual values in static values OR in the actual ASP.NET cache. This would allow you to continue to use the config api but allow you to change the implentation as needed.
I _think_ ASP.NET recyles the process and re-reads the config if the config changes so it may not actually be a benifit to save the values into cache, but that may be work double checking.
I took a quick peek at the other article, and frankly…this is where using the built-in configuration mechanisms come into play. Personally, I find app settings pretty much useless…I’d far rather have a strongly typed configuration system rather than a trivial NV collection for anything of consequence.
I believe someone referred to a tool that will help you do this, but it’s not exactly terribly difficult to do by hand…throw a few attributes on, it gets deserialized upon initial access and from then on, all is fine and good.
Simply reference it such as MyCoolAppSettings.Current.PropertyName
(should be a read only singleton…where the instance is created upon field initialization)