Browse > Home / Archive: August 2009

| Subcribe via RSS

Some thoughts on string concatenation in C#

August 20th, 2009 | 2 Comments | Posted in C#

I recently stumbled into a blog entry on CodeProject.com that stated some things about string concatenation in C# that went against what I thought to be true, and it got me thinking.

From the article:

string sentence = "The " + "dog " + "ate " + "the " + "cat " + "all " + "day " + "for " + "for " + "fun.";

”That innocent looking line of code actually takes up much more processing power and memory than it appears to. If strings were combined in the ideal way, you would expect that the sentence would be the only string created from this operation. However, since each string is combined to its neighbor in succession, it turns out that 7 other strings are also created (shown in gray in the diagram above). The total amount of unnecessary memory allocations created from this operation is equal to the following equation, where N is the number of strings you are combining…”

But I knew that couldn’t be true, so I fired up Visual Studio and wrote a few simple tests, compiled and then analyzed the generated CIL.

First test:

Original C#:

public string createStringOne()
{
    return "The " + "dog " + "ate " + "the " + "cat " + "all " + "day " + "for " + "for " + "fun.";
}

Generated CIL:

.method public hidebysig instance string createStringOne() cil managed
{
    .maxstack 8
    L_0000: ldstr "The dog ate the cat all day for for fun."
    L_0005: ret
}

Second test:

Original C#:

public string createStringTwo()
{
    return "The dog ate the cat all day for for fun.";
}

Generated CIL:

.method public hidebysig instance string createStringTwo() cil managed
{
    .maxstack 8
    L_0000: ldstr "The dog ate the cat all day for for fun."
    L_0005: ret
}

Third test:

Original C#:

public string createStringThree()
{
    var sb = new StringBuilder();
    sb.Append("The ");
    sb.Append("dog ");
    sb.Append("ate ");
    sb.Append("the ");
    sb.Append("cat ");
    sb.Append("all ");
    sb.Append("day ");
    sb.Append("for ");
    sb.Append("for ");
    sb.Append("fun.");
    return sb.ToString();
}

Generated CIL:

.method public hidebysig instance string createStringThree() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [mscorlib]System.Text.StringBuilder sb)
    L_0000: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
    L_0005: stloc.0
    L_0006: ldloc.0
    L_0007: ldstr "The "
    L_000c: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0011: pop
    L_0012: ldloc.0
    L_0013: ldstr "dog "
    L_0018: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_001d: pop
    L_001e: ldloc.0
    L_001f: ldstr "ate "
    L_0024: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0029: pop
    L_002a: ldloc.0
    L_002b: ldstr "the "
    L_0030: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0035: pop
    L_0036: ldloc.0
    L_0037: ldstr "cat "
    L_003c: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0041: pop
    L_0042: ldloc.0
    L_0043: ldstr "all "
    L_0048: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_004d: pop
    L_004e: ldloc.0
    L_004f: ldstr "day "
    L_0054: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0059: pop
    L_005a: ldloc.0
    L_005b: ldstr "for "
    L_0060: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0065: pop
    L_0066: ldloc.0
    L_0067: ldstr "for "
    L_006c: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_0071: pop
    L_0072: ldloc.0
    L_0073: ldstr "fun."
    L_0078: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    L_007d: pop
    L_007e: ldloc.0
    L_007f: callvirt instance string [mscorlib]System.Object::ToString()
    L_0084: ret
}

Fourth test:

Original C#:

public string createStringFour()
{
    return new StringBuilder("The dog ate the cat all day for for fun.").ToString();
}

Generated CIL:

.method public hidebysig instance string createStringFour() cil managed
{
    .maxstack 8
    L_0000: ldstr "The dog ate the cat all day for for fun."
    L_0005: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(string)
    L_000a: callvirt instance string [mscorlib]System.Object::ToString()
    L_000f: ret
}

Fifth test:

Original C#:

public string createStringFive()
{
    string s = "The ";
    s += "dog ";
    s += "ate ";
    s += "the ";
    s += "cat ";
    s += "all ";
    s += "day ";
    s += "for ";
    s += "for ";
    s += "fun.";
    return s;
}

Generated CIL:

.method public hidebysig instance string createStringFive() cil managed
{
    .maxstack 2
    .locals init (
        [0] string s)
    L_0000: ldstr "The "
    L_0005: stloc.0
    L_0006: ldloc.0
    L_0007: ldstr "dog "
    L_000c: call string [mscorlib]System.String::Concat(string, string)
    L_0011: stloc.0
    L_0012: ldloc.0
    L_0013: ldstr "ate "
    L_0018: call string [mscorlib]System.String::Concat(string, string)
    L_001d: stloc.0
    L_001e: ldloc.0
    L_001f: ldstr "the "
    L_0024: call string [mscorlib]System.String::Concat(string, string)
    L_0029: stloc.0
    L_002a: ldloc.0
    L_002b: ldstr "cat "
    L_0030: call string [mscorlib]System.String::Concat(string, string)
    L_0035: stloc.0
    L_0036: ldloc.0
    L_0037: ldstr "all "
    L_003c: call string [mscorlib]System.String::Concat(string, string)
    L_0041: stloc.0
    L_0042: ldloc.0
    L_0043: ldstr "day "
    L_0048: call string [mscorlib]System.String::Concat(string, string)
    L_004d: stloc.0
    L_004e: ldloc.0
    L_004f: ldstr "for "
    L_0054: call string [mscorlib]System.String::Concat(string, string)
    L_0059: stloc.0
    L_005a: ldloc.0
    L_005b: ldstr "for "
    L_0060: call string [mscorlib]System.String::Concat(string, string)
    L_0065: stloc.0
    L_0066: ldloc.0
    L_0067: ldstr "fun."
    L_006c: call string [mscorlib]System.String::Concat(string, string)
    L_0071: stloc.0
    L_0072: ldloc.0
    L_0073: ret
}

Results:

So as you can see, the first two methods are essentially the same thing!  It doesn’t matter if we concatenate one large string from several smaller strings if (and only if) it happens on one operation.  If concatenation is done using multiple operations, then it does in fact incur a performance and memory hit.

The use of a StringBuilder in this case (where there are only a small handful of small strings) serves no purpose as far as performance is concerned.

But… how are they equal!?

Compiler optimizations!  The C# compiler is an incredible piece of software that can look at your code and “fix” it.  It is important when working on code optimizations like the one in the article mentioned above that developers take into consideration compiler optimizations that may alter the code that they think is poorly written.

Add to Del.cio.us RSS Feed Add to Technorati Favorites Stumble It! Digg It!
    www.sajithmr.com

http://deserialized.com/wp-content/plugins/sociofluid/images/digg_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/reddit_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/dzone_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/delicious_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/newsvine_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/technorati_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/google_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/facebook_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/mixx_48.png

Comparing while() loops with for() loops in C#

August 19th, 2009 | 1 Comment | Posted in C#

There is always a lot of debate about the speed and performance of loops in any language.  I was curious to see what the differences were between a for() loop and a while() loop in C# and ultimately the .NET CLR.

What I found was no big surprise to me, as it simply confirms what I have been reading for many years.  While loops are simply faster and less complex than for loops.  I did a very simple test to verify this.  I created two loops that contained empty bodies.  You can see them below:

public void doFor()
{
    int i = 0;
    int len = 100;
 
    for (i = 0; i < len; i++)
    {
 
    }
}
public void doWhile()
{
    int i = 100;
    while (i-- == 0)
    {
 
    }
}

 

As you can see, both of these loops are as basic as they can be and have no inner bodies to complicate the CIL.  Lets take a look at the generated CIL for each of them.

 

The generated CIL for a for() loop

.method public hidebysig instance void doFor() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] int32 len)
    L_0000: ldc.i4.0 
    L_0001: stloc.0 
    L_0002: ldc.i4.s 100
    L_0004: stloc.1 
    L_0005: ldc.i4.0 
    L_0006: stloc.0 
    L_0007: br.s L_000d
    L_0009: ldloc.0 
    L_000a: ldc.i4.1 
    L_000b: add 
    L_000c: stloc.0 
    L_000d: ldloc.0 
    L_000e: ldloc.1 
    L_000f: blt.s L_0009
    L_0011: ret 
}

The generated CIL for a while() loop

.method public hidebysig instance void doWhile() cil managed
{
    .maxstack 3
    .locals init (
        [0] int32 i)
    L_0000: ldc.i4.s 100
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: dup 
    L_0005: ldc.i4.1 
    L_0006: sub 
    L_0007: stloc.0 
    L_0008: brfalse.s L_0003
    L_000a: ret 
}

 

The results are in and there is no surprise.

As you can see, the generated CIL for a for() loop is larger by 6 instructions. Furthermore, in this code the for() loop initializes 2 local variables rather than 1 (but this may vary depending on your code).

 

What does it all mean?

Probably nothing.  6 more instructions and an additional variable declaration will in most cases have no impact on the performance, even if you are measuring in microseconds.  I am curious to see what the resulting difference between the loops above would be in other languages.

Add to Del.cio.us RSS Feed Add to Technorati Favorites Stumble It! Digg It!
    www.sajithmr.com

http://deserialized.com/wp-content/plugins/sociofluid/images/digg_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/reddit_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/dzone_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/delicious_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/newsvine_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/technorati_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/google_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/facebook_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/mixx_48.png

WordPress 2.8 Pretty URLs and IIS6

August 18th, 2009 | 12 Comments | Posted in IIS, wordpress
WordPress

WordPress

For my first blog post, I thought it would be a good idea to write about the experience and process of setting up WordPress 2.8 on my Windows Server 2003 box with IIS6.  I wanted to enable pretty links (you know, without the ugly index.php prefix), but IIS6 does not support this sort of behavior out of the box.

Yes, I know – WordPress and PHP belong on Linux but I prefer to think of myself as a Windows developer (C#, ASP.NET), though I work full time developing with PHP, Java\JSP, and JavaScript.

Installing WordPress is pretty straight forward, so I wont bother getting into the easy stuff.  It is just a matter of extracting the files and creating a new web site in the IIS Manager with script execution permissions.  I am going to assume that you already have IIS and PHP running.  If you do not, read up on it at the IIS6 FastCGI forums on IIS.net.  You’ll find that Windows handles PHP and WordPress just fine, but you’ll be missing one major Linux\Apache feature – mod_rewrite.

mod_rewrite is the module that allows you to create those fancy “pretty URLs” that everyone loves so much (yes, I love them too).  IIS6 does not support this out of the box so we will need to install an ISAPI filter to accomplish this for us.  My favorite is the open-source Codeplex project IIRF.  I’ve used it in a number of projects and it always works out well for me.

For the remainder of this post I am going to assume that you already have a working WordPress installation.  On to the fun part…

Installing IIRF in IIS6

Download the latest build of IIRF from Codeplex and extract it to somewhere on your hard drive.  I usually have the following structure:

C:\inetpub\wwwroot\sitename.com
C:\inetpub\wwwroot\sitename.com\www
C:\inetpub\wwwroot\sitename.com\iirf

I do this to separate the web content from the ISAPI filter.  When you extract the archive, you’ll find there are a ton of files in there.  Most of them are for testing your rules but you only need the following two files:

IsapiRewrite4.dll
IsapiRewrite4.ini

The DLL is the actual ISAPI filter and is the equivalent of mod_rewrite on Apache and the INI file is the configuration file which is the equivalent of an .htaccess file on Apache.

Once you have the files extracted in the correct location you must enable the filter in IIS6.  Start by opening up the IIS Manager.  (I’ll assume you already know how to do this.)  On the left side, click on the [+] sign to expand the list.  You should see Application Pools, Web Sites, and Web Service Extensions.

Enabling the ISAPI filter is a two step process.  The first step is to add it as a Web Service Extension so click on that list item on the left.  The list of installed ISAPI filters will be shown on the right side.  Click on “Add a new Web service extension” and you’ll see the screen below:

new-web-service-extension

You may enter any name, but I would recommend that you enter something that identifies this filter so that you can easily remember what it is for.  A good idea is something like  “IIRF for MySite.com”  Once you have chosen a name, you must add the required files.  Click on Add and then click on Browse.  Navigate to the folder that you extracted the IsapiRewrite4.dll file and select it. Press OK.  You should now be looking at the “New Web Service Extension” window again, with one file listed in the “Required files” list.  Check “Set extension status to Allowed” and press OK.

The ISAPI filter is now allowed to run on this web server.  For the second step, you’ll need to tell IIS which sites will actually execute this filter.  Expand the “Web Sites” list by pressing the [+] button on the left.  Right click on the web site that you want to enable IIRF for and click Properties.  Select the “ISAPI Filters” tab and click Add.  For filter name you may enter anything you want.  I usually choose “IIRF” but you can enter whatever you want.  Next click on Browse and once again navigate to the same  IsapiRewrite4.dll file that you just selected in Step 1. Press OK to return to the web site properties window.  You should now see the filter listed in the filters list.  Assuming it all went according to plan, press OK again to return to the IIS Manager.

You may need to restart IIS at this point so the server loads the new ISAPI filters.

Setting up IIRF rewrite rules

This is the easy part.  IIRF supports many (but not all) of the same rewrite directives that mod_rewrite does.  It is worth noting that mod_rewrite is incredibly powerful and you can usually find rules for doing all sorts of cool things but they might not always work with IIRF due to lack of support with some mod_rewrite directives.  IIRF is still under development so the future may hold some good news, but your mileage may vary.

IsapiRewrite4.ini must reside in the same folder as IsapiRewrite4.dll.  If it does not exist, create the file now.  To enable pretty URLs for WordPress all we need to do is copy the contents of a valid .htaccess file from a typical Linux\Apache WordPress installation, which I have pasted here:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Save IsapiRewrite4.ini and then head over to your WordPress Administration panel.

Enabling Pretty URLs in WordPress

Log in to your WordPress Administration Panel and click on Settings and then on Permalinks.  Click on “Custom Structure” and enter the following:

/%postname%/

Now press Save.  At this point, you should be ready to go.  Head over to your blog and refresh it.  Click on some articles and look at the URL.  You should now have pretty, clean URLs.

Add to Del.cio.us RSS Feed Add to Technorati Favorites Stumble It! Digg It!
    www.sajithmr.com

http://deserialized.com/wp-content/plugins/sociofluid/images/digg_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/reddit_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/dzone_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/delicious_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/newsvine_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/technorati_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/google_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/facebook_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/mixx_48.png

Hello world!

August 18th, 2009 | No Comments | Posted in Uncategorized

Hello world.

This has been a long time coming – a blog. Somehow I managed to escape from blogging for the past several years but here I am now. There have been so many topics brewing in my head. Being a full time web developer for a kick ass company means that I am constantly tackling hard to solve problems and that means that there are always light bulbs going on over my head. I decided today that it is time to begin sharing those thoughts.

This blog will be about web development, web security, personal projects, and general programming. I don’t claim to be the best programmer alive, so some of the things I’ll write may not impress you – that’s ok, just don’t flame me. If you find what I say interesting, let me know.

It is time to start writing for real now. Until then….

Add to Del.cio.us RSS Feed Add to Technorati Favorites Stumble It! Digg It!
    www.sajithmr.com

http://deserialized.com/wp-content/plugins/sociofluid/images/digg_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/reddit_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/dzone_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/delicious_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/newsvine_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/technorati_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/google_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/facebook_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://deserialized.com/wp-content/plugins/sociofluid/images/mixx_48.png