Tuesday, October 26, 2010

Open Source Software Stupid Tax

I'm sure I read or heard this somewhere before but my searches have turned up nothing.

If you fix a bug or add a feature to an open source project and you don't contribute that bug back to the project this is referred to as the stupid tax.

The reason that you fixed this bug in the first place is because it was preventing you from using the open source software the way that you wanted to use it. It might not even be a bug, it might be a feature that was missing that you needed.

Not contributing it back to the project is a stupid tax because it means that each time you want to upgrade to the latest version of the open source code you have to reapply your fix or feature. This is going to cost you in time and if you don't get it right first time it may introduce further bugs into your system. If you have someone else working on the team and they decide to upgrade the open source project to the latest version they might not know that you had "modded" the OS project. You might not even know that the developer that you replaced on the team applied a patch to it and then you're left scratching your head and trying to work out why the upgraded OS code is not working with your project.

Don't pay the stupid tax. Get your fixes and features back into the open source project as soon as possible and give yourself a pain free upgrade path to further releases of the OS project.

Saturday, October 16, 2010

RunAs Utility

I've recently discovered (been introduced to) the runas command line utility which I was previously unaware of. This command allows you to run in the context of another user which is particularly useful if you are testing access permissions under different user names. The syntax is:

runas /user:mydomain\myuser program.exe

The one annoyance is that when you run that command it requires that you type in the password and if its a particularly long and complex password I will often make a mistake. However, because this is in a command window you can copy the password to the clipboard and right click at the password prompt and select Paste and it works.

Try running the following with a different user who is registered on your local computer.

runas /user:mydomain\myuser cmd

This will bring up a new command prompt in the context of that user. Now type the command...

whoami

...in both command windows. You will see that each command window is running in the context of a different user.

Improving security and reducing HTTP header size in IIS

I've identified four unnecessary HTTP header elements that get transmitted with one of my ASP.NET MVC2 web sites. I wanted to remove these headers to improve security and reduce header size and thought that it would be easy to remove these HTTP headers from IIS7 in the same manner. It turned out that each of them had to be removed with a different technique.

X-Powered-By: ASP.NET

This header is removed through the IIS Manager. You can remove it on a site by site basis or remove it for the server. If removed from the server then it's removed from all sites on that server. This is the approach I prefer.

  1. Bring up IIS Manager.
  2. Click on the server name in the left panel
  3. Under the IIS section in the server area you will see HTTP Response Headers, double click on this.
  4. Click on the line that says "X-Powered-By ASP.NET Local"
  5. In the Actions pane on the right click Remove.

Server: Microsoft-IIS/7.0

This one is a bit more tricky to remove and needed some code to be added to the web site.

In the MasterPage.master code behind file in the Page_Load function I put the following:

HttpContext.Current.Response.Headers.Remove("Server");

X-AspNet-Version    4.0.30319

To get rid of this one I had to edit the web.config file and set the enableVersionHeader attribute to false:

<httpRuntime enableVersionHeader="false" />

X-AspNetMvc-Version: 2.0

In the constructor for the Global class in the global.asax.cs file I set the static DisableMvcResponseHeader property of the MvcHandler class to true.

public Global()
{
      MvcHandler.DisableMvcResponseHeader = true;
}

Sunday, October 3, 2010

The Male Brain by Louann Brizendine

The Male Brain by Louann BrizendineJust finished The Male Brain by Louann Brizendine.

I was very surprised at how much I liked this book and how good it was. I can't remember who recommended it or why I picked it up because it's not the sort of thing I would have normally read.

I particularly enjoyed the section about the teenage male brain. Finally I don't feel so guilty about the way that I behaved when I was a teenager, I was wired to behave that way.

I believe that the male brain is a sequel to The Female Brain which I have not read and I'm not sure if you need to read it after reading The Male Brain. I say this because at every stage of life she compares and contrasts the male brain to the female brain so you're really learning about both and their differences.

At the end of the day the reason why we act the way that we do is because we have these chemicals marinating our brains and pushing us back towards the stone age man.

Nested Parallel.ForEach()

I recently wrote some code that was using Parallel.ForEach() and in the function called during the Parallel.ForEach() I nested another call to Parallel.ForEach() to process a second array. This then got me thinking. If the first array that you are processing is larger than the number of cores on the machine that you're running it on then there's no advantage to nesting a second Parallel.ForEach(). You might as well just loop in that function because we'll already have all the processors saturated. So I put together a test to see the difference between Parallel.ForEach() with a regular loop and Parallel.ForEach() with a nested Parallel.ForEach()

static void ParallelMainNestedTest()
{
    int[] lowerRange = Enumerable.Range(0, 10).ToArray();
    int[] upperRange = Enumerable.Range(1000, 1010).ToArray();

    Stopwatch timer = Stopwatch.StartNew();
    Parallel.ForEach(lowerRange, lowerValue =>
        DoItemNotNested(lowerValue, upperRange));
    Console.WriteLine("Not Nested: {0}", timer.Elapsed);

    timer.Restart();
    Parallel.ForEach(lowerRange, lowerValue =>
        DoItemNested1(lowerValue, upperRange));
    Console.WriteLine("Nested: {0}", timer.Elapsed);

    Console.ReadKey();
}

static void DoItemNotNested(int lowerValue, int[] upperRange)
{
    foreach (int upperValue in upperRange)
    {
        Thread.Sleep(10);
    }
}

static void DoItemNested1(int lowerValue, int[] upperRange)
{
    Parallel.ForEach(upperRange, upperValue =>
        DoItemNested2(lowerValue, upperValue));
}
static void DoItemNested2(int lowerValue, int upperValue)
{
    Thread.Sleep(10);

The results of this test showed:

Not Nested: 00:00:14.6155628
Nested: 00:00:09.0907248

Now the reason that I put a sleep in the inner loop of the two tests is because this test code is designed to simulate network access (a REST call to a site) and I wanted to create a test where there would be idle wait time to determine which strategy is better. I appears, as you can see, that a pair of nested Parallel.ForEach() calls is most efficient in this scenario.

What if there was no latency in the inner loop and it was all down to the speed of the processor?

My suspicion is that the nested Parallel.ForEach() would be slower because of the extra overhead in managing the extra threads. To test this I replaced the Thread.Sleep(10) call with the following:

static Random r = new Random(Guid.NewGuid().GetHashCode());
private static void DoSomething(int lowerValue, int upperValue)
{
    for (int i = 0; i < 5000; i++)
    {
        int rand = r.Next(lowerValue, upperValue);
        rand = rand * rand;
    }
}

The result:

Not Nested: 00:00:05.6169188
Nested: 00:00:06.1500767

Confirmed: The nested Parallel.ForEach() shows a degradation in performance because of the extra overhead in managing all those extra threads.

Conclusion: Used nested Parallel.ForEach()'s when you know that the inner loop will be waiting on external resources (database, disk, network etc.). Use regular looping in the inner loop if you are doing a math or algorithmic intensive calculation that relies on the CPU alone.