I finally managed to do some timing with the globalization support. I wrote a small Application Center Test script that retrieves the test application web page 2000 times. I ran the test on my laptop (1.5 GHz, 512 MB) under a number of different scenarios. Here are the results:
1) Globalization disabled: 117.6 RPS (requests per second)
2) Globalization enabled, no caching: 83.3 RPS
3) Globalization enabled, with caching: 90.1 RPS
4) Globalization enabled, allocate ResourceManager on every request: 57.1 RPS
5) Globalization enabled, no DataListLocalizer, with caching: 95.2 RPS
6) Globalization enabled, no DataListLocalizer, no caching: 90.1 RPS
In scenario 1, I disabled globalization by commenting out the line that adds the HttpModule in web.config. In scenario 2, I enabled globalization. This tests effectively the code in the sample application. In scenario 3, I added caching of localized strings. On first request, I get the localized string from the resource with ResourceManager.GetString and store it into Page.Cache. On subsequent requests for the same string and language, I get the string from the cache. Finally, in scenario 4, I modified the code so it allocates the ResourceManager every time it is needed. In all other tests the ResourceManager is allocated once and stored into the HttpApplicationState object for later use.
In scenarios 5 and 6 I took away the DataListLocalizer attribute attached to the DataList used in the Menu control. The DataListLocalizer does another pass over the rows in the DataList and not surprisingly this is a pretty costly thing to do. In real life, we'd be better off localizing the contents of the DataList by e.g., binding it to the result of an SQL query that returns the strings already localized.
In short, I conclude that reflection and recursion do add an overhead of about 20% compared to no globalization. This is more than I had hoped, but then again, in a real-life application that does actual work (e.g., retrieves stuff from the database) the relative overhead is smaller.
Caching localized strings into Page.Cache does improve performance. The improvement is due to the fact that caching resource strings reduces the number of times we call ResourceManager.GetString. The price of course is bigger memory footprint - you should measure whether the price is worth paying.
I made the experiment in scenario 4 to see the effect of allocating a ResourceManager every time one is needed. It shows clearly that doing so will have a big negative effect on performance. Allocating the ResourceManager once and storing it for later use improves performance, but again at the price of increased memory usage.
In conclusion, localizing simple controls through attributes and reflection is a viable method. More complex controls and content should be localized in a way that does not require an additional pass over the data. Page throughput can be increased through caching localized strings and the ResourceManager instance. Caching is a balancing act as the bigger memory footprint may actually end up hurting performance - as always, you should measure what works best in your case.
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.