Thursday, January 14, 2010

Tips For Web Developers: Minify Javascript Using Google's Closure Compiler

A faster web site is a goal for every develoepr. We spend a lot of time optimizing server code and processes, parallelizing stuff, indexing
and trying to enhance database performance. The goal behind all of these complicated actions is the ultimate goal: A Faster Site.
These actions are necessary and handy to decrease your site response time, however, there are a lot of stuff that we, developers, usually ignore. Those are the optimizations required to happen on the client side. These client side optimizations are as important (probably more imprtant) as the server side optimizations.
There are a lot of techniques to optimize the client side performance. These techniques include:


  • Making Less HTTP Requests
  • Optimizing JavaScript
  • Optimizing CSS


And many more. For full details about all the possible techniques, check out Google's page speed initiative.
In this post I will focus on optimizing javascript by minifying js files. For this I leverage Closure Compiler, which is a very awesome tool to optimize Javascript developed by Google.
Now suppose that I have an html document that looks like the following:




This document shall do a very little job actually. Simply a user keys his name in the textbox and clicks salute me which we will display a simple alert saying hello to this user.

Below are two buttons -hide, and show. As the name of each button implies, the hide button will hide the area including the label, text box, and the Salute me button.

To do this I'm gonna make use of jQuery 1.3.2. Here's the code needed to achieve the required functionality:
/*
 The follwoing code is not part of jqueyr framework
*/
$(document).ready(function() { 
 $('#hiFiver').click(function() { 
  var userName = $('#txtName').val();
  alert ("Hello " + userName); 
 });
 
 $('#showButton').click(function() { 
  $('#hidden').show();
 });
 
 $('#hideButton').click(function() { 
  $('#hidden').hide(); 
 });
});
 For the sake of this demo I will append my code at the end of the actual jQuery code itself. Now my app is working as required, and my Javascript file  size is 122 KB.

 Now let's run Closure Compiler and try to minify this.
 Closure Compiler is a java application, which means that you will need jre (Java Runtime Engine) to run it. You can download it from here

 Now I got my files (sample.html, script.js, compiler.jar) in one directory. To run the compiler, launch your terminal, and enter the follwoing command:

 java -jar compiler.jar --js script.js --js_output_file scriptMini.js

 Check your directory. You should find a new file with the name "scriptMini.js" created. The new script file is 55 KB in size, which is less the half size  of the original file. To make sure it's working, change the script src attribute in the sample document to point to the new file. You should see that  the app is still functioning  properly.

 If you examin the newly created file, you will find that it doesn't contain any comments or spaces, all the optional semi-colons are removed, variable names are  changed to shorter names (usually one character long).

 The closure complier is a fascinating tool, it's really handy and easy to use.
 From now on you should develop the habit of always minifing your Javascript files.

Wednesday, January 13, 2010

Why is O(n) Is Pronounced "Big Oh" of n And Why Is "Geek" So Close To "Greek"?



This one is really short, Today, some guy on the internet asked why is the asymptotic form O(n) is pronounced Big Oh? I instantly answered "because we are using the capital letter O to write it".

This answer is wrong, the letter used is the Greek letter Omicron.
So that's why it's pronounced Big Oh!




And the same reason applies to Big Theta, and Big Omega, because of using the Greek letters Theta and Omega represented in the above picture (the second and third figure respectively). It's all coming from the Greeks buddy!
And probably this is also why the word Geek is so close to the word Greek in spelling, I'm not sure about this one though.


Remove Duplicate Items From an Array - A Classic Puzzle

 Today I cam a cross a kinda cool problem. A friend of mine who is at the same time a colleague working with me at the same office was trying to remove a duplicate item from an array of positive integers.
 The array has n items all unique except only one item. We need to come up with an algorithm that tells us which item is duplicated in maximum time of
 O(n) where n is the length of the array.

 To do that, let's first come up with some (less efficient) working algorithms. Here's the first one:

 We loop over the array starting from the item at index 0, then we traverse the remaining part of the array (1 : n-1) searching for the first item
 The C# code for this algorithm looks like the following:
  static int FirstDuplicate(int[] arr)
         {
             for(int i = 0; i < arr.Length - 1; i++)
             {
                 for(int j = i + 1; j < arr.Length; j++)
                 {
                     if (arr[i] == arr[j])
                         return arr[i];
                 }
             }
             return -1;
        }
 As you can see, this algorithm is pretty bad. Foreach item in the array an inner loop is initiated to linerally look for that specific element in the
rest of the array. If you do the math, you shall find that this algorithm runs in O(n2) order of growth.

One way to improve this is to use an extra HashSet to store the items, and then look up each item in the HashSet. This is considered improvement as the
lookup inside the HashSet is really fast.
Here's the code in C#:

 static int FirstDuplicateWithHashSet(int[] arr)
        {
            HashSet hashHset = new HashSet(); 
            for(int i = 0; i < arr.Length; i++)
            {
                if (hashHset.Contains(arr[i]))
                    return arr[i];
                hashHset.Add(arr[i]);
            }

            return 0;
        }
This is pretty good, but still not O(n).
The next algorithm is quite tricky. The idea simply is to create a second array and insert each elemnt in the first array at an index equivalent to its
value in the second array.
For example if we have a list of 5 items [2, 4, 5, 2, 6], where the item 2 is duplicated at the 0 index and third index, and the maximum value in this
array is 6. Now to find the duplicates in this list we create a second list with length 6 ( the length of the second array equals the maximum value in
the first array). After creating this second list we loop over the first array take the first item (2 in our case) and insert it at the index 2 in
the second array, then we take the second item (which is 4) and insert it at the 4th index in the second array, and so on. Each time we try to insert
an item in the second array we check if it has a value first, if it is, then this item is duplicated.
here's how the code would look like:

static int FirstDuplicate(int[] arr, int maxVal)
        {
            int[] temp = new int[maxVal+1];
            for(int i =0; i < arr.Length; i++)
            {
                if (temp[arr[i]] == arr[i])
                    return arr[i];
                temp[arr[i]] = arr[i];
            }
            return 0;
        }
 Note: The method expects the maximum value as an input, however, if you don't get the maximum value you can create the temp array with a size
 equal to  int.MaxValue (which is not a good idea)

 This algorithm is probably not realistic but it doesn run in O(n) time.
 One more trick to add here, if you know the range of the items in the array (e.g. from 1 to 10) you can get the sum of the numbers of the array
 then subtract from it the sum of the numbers from 1 to 10, the remainder is the duplicated value.

 That was a quick tip that I thought is cool and wanted to share with ya! So what do you think dear fellows? Do you know of any possibly better
 algorithms? Do you suggest any optimization to the current ones?

Wednesday, January 6, 2010

Scalability Tip In ASP.NET And The MachineKey Element

Yesterday, I came a cross a pretty annoying problem with a web application I'm working on nowadays.
In short, the app is an ASP.NET MVC 1 app, that uses forms authentications to handle users logins.
The app was working just fine, but when I started to scale the app and deploy it to more servers in the server farm, the weired behavior started to show up. When a user logs in to the application, the application preforms the operation successfully, logs in the user to the system and takes him to his personalized page. That sounds normal, however, if the user navigated to another part of the application (or just refreshes the current page), the application no longer recognizes him as a logged in user! If he refreshes two or three times, the app will see him as a logged in user again, a few more refreshes and he's nor more logged in and so on.

Similar Problem: 
I encountered  a similar problem before, but the other one was because of accidental session expiration, and this happened because I was saving SessionState InProc, which (as you may have guessed) will be stored on the server memory (i.e. will not be shared between all server in the web farm).

This Problem: 
This problem is different because I'm not using SessionState at all. I'm just using cookies and you know that cookies are stored on the client, and is sent to the server with every request, so it will be sent to all servers (i.e. all servers should be able to read the cookie and determine if the user is logged in or not).

How Cookies Are Written: 
This got me thinking, the problem must be with the cookie itself. It seems like some servers can read the cookie successfully, and some can't. Why would that be?!!

Different Encryption/Decryption Key/Algorithm:
Aha .... Cookies are encrypted before they are written on the client and decrypted before they are read again by the server. When the server that served the login request wrote the cookie, it encrypted it first (using an AutoGenerated encryption key and its chosen encryption algorithm. So apparently the chosen encryption keys and/or algorithms are different across the severs!

The Solution: 
The solution is quite simple actually. All I need to do is to ensure that all the servers use the same encryption algorithms and keys.
This can be done by explicitly specifying the keys and algorithms in web.config inside the machineKey  tag. 
It should look something like this:



PS: The keys lengths depend on the algorithms selected

  • For SHA1, set the validationKey to 64 bytes (128 hexadecimal characters).
  • For AES, set the decryptionKey to 32 bytes (64 hexadecimal characters).
  • For 3DES, set the decryptionKey to 24 bytes (48 hexadecimal characters).


The keys can be generated whatever way you like. Here's a simple function for generating these keys: 




static string GenerateKey(int requiredLength)
    {
        byte[] buffer = new byte[requiredLength / 2];
        RNGCryptoServiceProvider rng = new
                                RNGCryptoServiceProvider();
        rng.GetBytes(buffer);
        StringBuilder sb = new StringBuilder(requiredLength);
        foreach (byte t in buffer)
            sb.Append(string.Format("{0:X2}", t));
        return sb.ToString();
    }





For more information about the tag see here, and here to how to configure it, and if you wanna scroll a full page see this for recommendations about deploying to server farms. 

Hope this helps.

Mix 2010 and My Chosen Sessions

Mix 2010 is open for public!



Microsoft is using a different strategy for a major conference (Mix) this year. Developers and designers can now submit their sessions and those sessions will be voted up by the community. The chooses sessions will be included in the conference.
Here's a list of all the sessions available for voting. The voting started yesterday, Jan 5th. and will last for for 10 days. The selected sessions will be announced Jan 18th.
Go ahead and vote for your session of choice. A lot of sessions out there? Would you like me to recommend some sessions to you?
O.K I will ....
Here are the sessions that I voted for:

Go ahead now, visit VisitMix.com and vote!