September 2008 - Posts

netdev I know the title of this post is a little bit of a misnomer, business objects will never map 1 to 1 with relational database objects.  However, when just starting out and when you get to control the schema of the database, it sure makes a good starting point and this trick makes it really easy and avoids a lot of typing.  It supports SQL 2005 and SQL 2008.


The first step is to download the script. The script I wrote to do this can be found at

Once the script has been downloaded, open it in SQL Server Management Studio and fill in the fields for Database name and Table Name.

Set Settings for Property Generation

After the settings are set run the script.  You should get something that looks a lot like:


Result Properties

Next, select all of the rows that are part of the table you are creating the class for.  Notice that my selection excludes the first column.  After the rows are selected, copy the rows out of the results grid.  Next, open up your project in Visual Studio.  Create a new class with the appropriate name and paste the contents of the clipboard as shown below.

Paste copied Code

The act of pasting the code into a class will cause the code to be formatted.  This should create nice looking properties inside of your class.

Newly Created Class

And that is all there is to it.  You will notice that by default the properties are sorted first by data type (desc), then by column name.  You can change this sort by changing the SQL Script if you wish.  I tend to like to group like-types together and then alphabetize.  I think it makes it a little more readable.  Also, we are using auto-implemented properties (aka Automatic Properties).


If you use the script or have comments / suggestions, please leave a comment and let me know!


This is just a quick post.  I had a bug where any time I tried to compile a WPF project on my laptop I got the following pair of errors:

Error Message 1:
The "SplashScreen" parameter is not supported by the "MarkupCompilePass1" task. Verify the parameter exists on the task, and it is a settable public instance property.

Error Message 2:
The "MarkupCompilePass1" task could not be initialized with its input parameters.

I completely uninstalled Visual Studio 2008 & SP1 and reinstalled everything and this did not go away.  Anyway, here is how you fix it:

  1. Using a text editor, open the file: C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.WinFx.targets
  2. Search for "MarkupCompilePass1"; this was line 294 for me
  3. Remove the following line from the XML tag line: SplashScreen="@(SplashScreen)"


I have also posted my work around on the Microsoft Connect site (link below).



Threading Recently I have been doing a lot with threading.  This is a concept that used to be very difficult for me and now is only just difficult! smile_regular  Threading is becoming increasingly important as modern processors are not getting faster, they are getting more cores.  In order for a application to utilize any of the power of modern CPU's it must use threading! So I thought I would take a second and go through all of the classes in the System.Threading namespace.  We'll start with the simple stuff and move on to more advanced stuff!

The most familiar and basic structure for locking in .net is the lock statement shown below:

lock (this) {
    ObjectCount = value;

The lock is a simple synchronization structure which will only allow a single thread into the "critical" locked section at a time.  Many people don't realize this but the following code does the exact same thing:

    ObjectCount = value;

In fact, the Monitor object can do a lot more than enter a critical section; though I've not found a lot of use for the other functions.  But some operations of note are Monitor.TryEnter which allows you to specify a time span to wait for the lock.  Monitor.Pulse and Monitor.PulseAll notify the next waiting thread or all waiting threads respectively that a lock has been released.  This is not necessarily required but may result in the next thread being able to enter the critical section a bit quicker.  Monitor.Wait will release the lock to let another thread enter and then re-acquire the lock. 

Another note-worthy threading trick is the keyword volatile. This designation is useful in conditions where we are waiting for a variable to be changed in a while loop.  The C# compiler is really smart and usually assumed volatility for you, but it's a great habit to use it explicitly.  Basically what it does is it does not allow the value of a variable to be cached in a register or a stack.  Any time the value is referenced it will be pulled from it's memory location on the stack.  If this were not the case the value could change and you may never break out of the while loop.  Here is a quick example:

private volatile bool IsCanceled;

private void RunThread(object state) {
    while (!IsCanceled) {
        // Do work here!

In the code block above, if some other thread changes the state of IsCanceled then the while loop will stop and the thread will exit.  While this is the behavior you would expect anyway the compiler might not agree with you (especially if there is late-binding or the value is modified outside of the scope of the class).  This keyword only works on fields, not properties and should only be used where it must as it will adversely affect performance.  Again, it's just good practice to use it when reading a value that can be mutated by another thread.

One of my favorite patterns is the singleton pattern.  This pattern is the most widely recognized but the least understood.  Lets take a second to examine a standard implementation of the singleton pattern.

public class SingletonExampleClass {

    private static volatile SingletonExampleClass _instance = null;

    public static SingletonExampleClass Instance {
        get {
            if (_instance == null) {
                lock (typeof(SingletonExampleClass)) {
                    if (_instance == null) {
                        _instance = new SingletonExampleClass();
            return _instance;

As you can see from the code above we have to implement double-checking.  The reason is that after the evaluation another thread could be slightly ahead and have created the object just ahead of you.  You could lock the type before doing your check in the first place but locking is expensive and completely unnecessary most of the times.  Only the first call requires the lock, after that all other calls simply want an a reference to that class.  Singleton is a very important pattern for serialization and is one of the most common, that's why Microsoft gave us a break here with the readonly keyword.  The same section of code above can be written as:

public class SingletonExampleClass {

    public static readonly SingletonExampleClass Instance = 
        new SingletonExampleClass();


Much simpler! It literally eliminated 12 lines of code!  This is more or less the same as it's brother.  The only difference is the lazy instantiation in the first example, but in almost all cases this pattern is simpler and more intuitive.  This pattern is also a little more flexible as it will allow you to use readonly on non-static fields as well.  Additionally you may instantiate the value in the constructor rather than the initializer, but you must do one or the other.  Also, once the value is set it may not be changed!

Another favorite of mine is the Interlocked class.  Interlocked.Increment and Interlocked.Decrement allows you to increment or decrement an numeric value using a thread-safe mechanism. 

private int ItemsProcessed = 0;

private void RunThread(object state) {
    List<Order> orders = state as List<Order>;
    if ( orders == null )

    foreach (Order ord in orders) {
        // Process Order
        // ...
        Interlocked.Increment(ref ItemsProcessed);

As you can see, it's pretty simple to  use.  You may be wondering about the use of ref in the function signature.  Well, as you know int and long are value types (structs) and would be passed to any function by value (copying the contents to the function).  When we use the ref function signature it tells the compiler that we don't want to pass a copy of this value to the function, we want to pass the actual variable.  I.E. we passed a pointer to the variable rather than the value of it. This means that any mutations made to the variable inside of the function are effective outside of the function. 

The next basic structure I'd like to discuss is a Mutex.  A Mutex is a lot like the Monitor object I showed above and a ManualResetEvent but can work between different processes, not just different threads.  The specifics of a Mutex are best described in this snippit from the MSDN documentation:

Mutexes are of two types: local mutexes, which are unnamed, and named system mutexes. A local mutex exists only within your process. It can be used by any thread in your process that has a reference to the Mutex object that represents the mutex. Each unnamed Mutex object represents a separate local mutex.

Named system mutexes are visible throughout the operating system, and can be used to synchronize the activities of processes. You can create a Mutex object that represents a named system mutex by using a constructor that accepts a name. The operating-system object can be created at the same time, or it can exist before the creation of the Mutex object. You can create multiple Mutex objects that represent the same named system mutex, and you can use the OpenExisting method to open an existing named system mutex.


On a server that is running Terminal Services, a named system mutex can have two levels of visibility. If its name begins with the prefix "Global\", the mutex is visible in all terminal server sessions. If its name begins with the prefix "Local\", the mutex is visible only in the terminal server session where it wa s created . In that case, a separate mutex with the same name can exist in each of the other terminal server sessions on the server . If you do not specify a prefix when you create a named mutex , it takes the prefix "Local\". Within a terminal server session, two mutexes whose names differ only by their prefixes are separate mutexes, and both are visible to all processes in the terminal server session. That is, the prefix names "Global\" and "Local\" describe the scope of the mutex name relative to terminal server sessions, not relative to processes .

Here is a short sample that checks for the an existing Mutex and exits if found.  This is useful for single-instance applications.

static class Program {

    static Mutex m;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main() {
        // Check for single instance of our application
        bool createdNew;
        m = new Mutex(true, "TestThreadingApplication", out createdNew);
        if (!createdNew) {
        Application.Run(new Form1());

The code works by trying to get an existing Mutex named "TestThreadingApplication".  If that Mutex does not exist in the Operating System it will be created and your thread will be assigned the owner.  If you were the first instance you will have created the Mutex and you may resume execution, otherwise your application will exit.

The last thing we will discuss in this post is a Semaphore.  A Semaphore works much the same way as a Mutex, but works best as a way to manage a pool of objects.  The Semaphore starts with an initial count of objects.  Each time the WaitOne method is called the count will be decrement.  When the count reaches zero threads will be blocked until another thread calls Release.  Unlike the Mutex, the Semaphore does not track which threads have incremented or decremented the internal count so the programmer must be careful to Release the exact number of times WaitOne is called.  It's best to think of a Semaphore as a synchronization mechanism that can let more than one thread into the critical section.  Because of it's similarity to other synchronization objects I didn't create a sample code block.



here is some great code for moving a window without a title bar. 

Step 1: Make your window transparent

<Window x:Class="TestWpfApp.Window1"
    Title="My WPF Application" Height="300" Width="300">

Step 2: Make a new title bar

    <Rectangle HorizontalAlignment="Stretch"  VerticalAlignment="Top" 
Height="40" MouseDown="move_window" /> </Grid>

Step 3: Add some code

using System.Runtime.InteropServices;
using System.Windows.Interop;

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;

public static extern int SendMessage(IntPtr hWnd, int Msg, 
int wParam, int lParam);
public static extern bool ReleaseCapture();

Step 4: Write the event

public void move_window(object sender, MouseButtonEventArgs e) {
    SendMessage(new WindowInteropHelper(this).Handle, 


with 1 comment(s)
Filed under: , ,

chrome-205_noshadow Google has done it again!  In a completely unexpected (at least by myself) move they have released a browser into mainstream.  Frankly, I am quite surprised!  Google was such a fan of Firefox that I never thought I would see them in competition.  It also surprises me because building web browsers has is not part of Google's core business.  This is also an obvious swipe at Microsoft which doesn't excite me.  A friend of mine upon hearing the news said "I don't like the idea of any major web presence building a major web browser and driving a supposedly "open source" technology to do what suits them best."


I have no idea how large the install really is.  The download is a tool that downloads the rest of the browser.  It downloaded for a few min's and began the install.  My estimation was it was probably about 10-30MB though I really don't know. The installation was very uneventful.

What Google did right

There are a few things I really like.  Here they are:

  1. The interface is nice, sleek, and small.  I hate browsers (Firefox, you know who you are) that take up TONS of vertical space on my screen!  The space is wasted with things I don't even need or want!  Google's chrome did a nice job here!
  2. I like the idea of a multi-threaded browser (even if it is a multi-process browser).
  3. JavaScript is now a 1st class language in chrome.  V8, the JavaScript execution engine It is runs JavaScript much the same way as managed code being JIT'ed directly to the CPU. As a result, it is LIGHTNING FAST!
  4. I really like the 'URL Bar'.  It has a suggest/append that actually gets what I want!  I also like the landing page.
  5. I like what they did to get the "sandbox" mode.  I especially like the way it's transparent to the user what is crashing your browser (usually a plug-in).
  6. I like the incognito feature which allows zero trace browsing.  I don't know why we don't do this all of the time! 
  7. The browsing experience is very fast.  The browser UI is also fast.
  8. I like the tab reordering.  It's very smooth!
  9. I think the "move tab to another Google browser window" is cool but ultimately not very useful.
  10. I like the "task manager"

What Google didn't do right

  1. The multi-process approach is a turn off.  This means that they have to have a JavaScript rendering engine in memory for each process, it means that things like settings, etc exist in each process.  Most of all processes are EXPENSIVE!  Very much overkill!  Yes, I know that this is how IE does it, and I've never liked it!
  2. The browser is too simple and has very little customization out of the box.
  3. It uses a *lot* of system resources! Especially Memory!
  4. I do not like that it uses a lot of the same code as Safari!  SAFARI NEEDS TO DIE!  IT SUCKS!!!  HOW MANY YEARS DO WE HAVE TO WAIT FOR HTTP1.1 PROGRESSIVE DOWNLOADING?  This is a big deal in my opinion.
  5. It has a book marking system that claims to be different but sure looks exactly like IE7 bookmarks to me!
  6. It was using a lot of my CPU!  Something like 60% of my CPU was going toward chrome!  I may have had a malfunctioning plug-in but even when I closed the tabs that looked like the culprit it was still using 11-17% of my CPU!
  7. It didn't seem to start up any faster than IE8 or FF3.
  8. Google didn't release anything until now.  So far as I know there wasn't even a beta version for users to try.  I looked for some plug-ins but couldn't find any.  A little heads up to the development community could have had many plug-ins available by the time the browser launched.
  9. I know this is a small thing, but I hate when the browser "styles" text boxes for me!  What if I wanted to implement my own highlighting?  What if I didn't want it to highlight?
  10. It would lie to me about processor usage!  I had a process that was using 45% of my CPU and that none of the processes claimed to take that much CPU.  This was a Gmail tab, ironically!
  11. Silverlight didn't work.  It tired, but never really loaded.

I've never been comfortable with Google's privacy policy.  The fact that it reads my G-Mail and suggests products much like the topics inside rubs me the wrong way.  The fact that they would like to track everything you do including every web page you visit SCARES ME!

Anyway, here are some JavaScript comparisons.  I only have IE8 (which isn't going to be ready for such tests) so those tests aren't very relevant.

Google vs IE 8 (in IE 7 Emulation Mode)

TEST                   COMPARISON            FROM                 TO             DETAILS


** TOTAL **: 4.93x as fast 18324.4ms +/- 1.9% 3716.2ms +/- 3.5% significant


3d: 6.99x as fast 1816.8ms +/- 4.1% 260.0ms +/- 11.7% significant
cube: 10.5x as fast 645.2ms +/- 5.8% 61.6ms +/- 8.8% significant
morph: 3.96x as fast 481.8ms +/- 11.0% 121.6ms +/- 21.7% significant
raytrace: 8.98x as fast 689.8ms +/- 3.4% 76.8ms +/- 18.2% significant

access: 19.5x as fast 3398.4ms +/- 1.3% 174.6ms +/- 11.1% significant
binary-trees: 47.3x as fast 482.4ms +/- 5.7% 10.2ms +/- 5.5% significant
fannkuch: 18.2x as fast 1199.0ms +/- 1.4% 65.8ms +/- 29.0% significant
nbody: 21.6x as fast 1322.4ms +/- 1.5% 61.2ms +/- 14.0% significant
nsieve: 10.6x as fast 394.6ms +/- 8.9% 37.4ms +/- 17.0% significant

bitops: 18.4x as fast 2197.0ms +/- 3.1% 119.2ms +/- 11.7% significant
3bit-bits-in-byte: 38.1x as fast 327.6ms +/- 7.1% 8.6ms +/- 7.9% significant
bits-in-byte: 24.5x as fast 485.2ms +/- 3.2% 19.8ms +/- 19.6% significant
bitwise-and: 25.4x as fast 858.2ms +/- 2.8% 33.8ms +/- 9.5% significant
nsieve-bits: 9.23x as fast 526.0ms +/- 7.3% 57.0ms +/- 19.9% significant

controlflow: 77.7x as fast 435.0ms +/- 1.8% 5.6ms +/- 12.2% significant
recursive: 77.7x as fast 435.0ms +/- 1.8% 5.6ms +/- 12.2% significant

crypto: 10.8x as fast 1176.4ms +/- 3.6% 108.6ms +/- 12.5% significant
aes: 12.2x as fast 518.8ms +/- 9.1% 42.6ms +/- 11.4% significant
md5: 8.04x as fast 318.4ms +/- 6.2% 39.6ms +/- 33.3% significant
sha1: 12.8x as fast 339.2ms +/- 7.3% 26.4ms +/- 9.8% significant

date: 1.87x as fast 1739.4ms +/- 5.1% 928.4ms +/- 6.6% significant
format-tofte: 1.57x as fast 733.8ms +/- 6.9% 468.6ms +/- 6.0% significant
format-xparb: 2.19x as fast 1005.6ms +/- 8.6% 459.8ms +/- 9.9% significant

math: 6.73x as fast 1607.6ms +/- 4.9% 239.0ms +/- 15.2% significant
cordic: 4.79x as fast 676.4ms +/- 5.9% 141.2ms +/- 27.4% significant
partial-sums: 5.98x as fast 443.4ms +/- 4.3% 74.2ms +/- 18.6% significant
spectral-norm: 20.7x as fast 487.8ms +/- 12.2% 23.6ms +/- 19.9% significant

regexp: *1.07x as slow* 719.6ms +/- 3.6% 767.2ms +/- 3.3% significant
dna: *1.07x as slow* 719.6ms +/- 3.6% 767.2ms +/- 3.3% significant

string: 4.70x as fast 5234.2ms +/- 2.4% 1113.6ms +/- 5.4% significant
base64: 15.8x as fast 2212.6ms +/- 4.4% 139.6ms +/- 20.7% significant
fasta: 9.57x as fast 1117.2ms +/- 2.8% 116.8ms +/- 7.5% significant
tagcloud: 1.86x as fast 597.0ms +/- 3.4% 321.4ms +/- 8.5% significant
unpack-code: 1.82x as fast 710.8ms +/- 3.8% 391.2ms +/- 3.3% significant
validate-input: 4.13x as fast 596.6ms +/- 1.8% 144.6ms +/- 10.4% significant

Google vs Firefox 3

TEST                   COMPARISON            FROM                 TO             DETAILS


** TOTAL **: 1.65x as fast 6138.2ms +/- 27.7% 3716.2ms +/- 3.5% significant


3d: 3.31x as fast 860.8ms +/- 66.9% 260.0ms +/- 11.7% significant
cube: - 422.8ms +/- 114.5% 61.6ms +/- 8.8%
morph: 1.68x as fast 204.6ms +/- 1.6% 121.6ms +/- 21.7% significant
raytrace: 3.04x as fast 233.4ms +/- 40.0% 76.8ms +/- 18.2% significant

access: 6.01x as fast 1049.8ms +/- 31.9% 174.6ms +/- 11.1% significant
binary-trees: - 185.2ms +/- 168.8% 10.2ms +/- 5.5%
fannkuch: 7.25x as fast 477.2ms +/- 8.9% 65.8ms +/- 29.0% significant
nbody: 3.98x as fast 243.4ms +/- 11.2% 61.2ms +/- 14.0% significant
nsieve: 3.85x as fast 144.0ms +/- 10.4% 37.4ms +/- 17.0% significant

bitops: 5.52x as fast 657.8ms +/- 2.2% 119.2ms +/- 11.7% significant
3bit-bits-in-byte: 13.2x as fast 113.4ms +/- 7.2% 8.6ms +/- 7.9% significant
bits-in-byte: 8.76x as fast 173.4ms +/- 6.4% 19.8ms +/- 19.6% significant
bitwise-and: 4.44x as fast 150.0ms +/- 12.0% 33.8ms +/- 9.5% significant
nsieve-bits: 3.88x as fast 221.0ms +/- 2.5% 57.0ms +/- 19.9% significant

controlflow: 12.8x as fast 71.8ms +/- 5.1% 5.6ms +/- 12.2% significant
recursive: 12.8x as fast 71.8ms +/- 5.1% 5.6ms +/- 12.2% significant

crypto: 3.29x as fast 357.0ms +/- 6.3% 108.6ms +/- 12.5% significant
aes: 3.37x as fast 143.6ms +/- 11.4% 42.6ms +/- 11.4% significant
md5: 2.73x as fast 108.2ms +/- 9.9% 39.6ms +/- 33.3% significant
sha1: 3.98x as fast 105.2ms +/- 3.1% 26.4ms +/- 9.8% significant

date: *1.73x as slow* 537.8ms +/- 43.8% 928.4ms +/- 6.6% significant
format-tofte: ?? 359.8ms +/- 56.1% 468.6ms +/- 6.0% not conclusive: might be *1.30x as slow*
format-xparb: *2.58x as slow* 178.0ms +/- 19.3% 459.8ms +/- 9.9% significant

math: 2.59x as fast 619.0ms +/- 12.5% 239.0ms +/- 15.2% significant
cordic: 1.93x as fast 272.6ms +/- 6.1% 141.2ms +/- 27.4% significant
partial-sums: 3.14x as fast 233.0ms +/- 35.7% 74.2ms +/- 18.6% significant
spectral-norm: 4.81x as fast 113.4ms +/- 9.1% 23.6ms +/- 19.9% significant

regexp: *1.68x as slow* 457.0ms +/- 7.7% 767.2ms +/- 3.3% significant
dna: *1.68x as slow* 457.0ms +/- 7.7% 767.2ms +/- 3.3% significant

string: - 1527.2ms +/- 37.5% 1113.6ms +/- 5.4%
base64: - 145.0ms +/- 12.2% 139.6ms +/- 20.7%
fasta: 3.01x as fast 351.2ms +/- 49.9% 116.8ms +/- 7.5% significant
tagcloud: ?? 311.8ms +/- 71.6% 321.4ms +/- 8.5% not conclusive: might be *1.03x as slow*
unpack-code: 1.28x as fast 501.0ms +/- 14.4% 391.2ms +/- 3.3% significant
validate-input: - 218.2ms +/- 54.4% 144.6ms +/- 10.4%


Google vs IE 8

TEST                   COMPARISON            FROM                 TO             DETAILS


** TOTAL **: 4.70x as fast 17474.2ms +/- 1.6% 3716.2ms +/- 3.5% significant


3d: 6.87x as fast 1786.8ms +/- 1.8% 260.0ms +/- 11.7% significant
cube: 10.1x as fast 620.0ms +/- 5.4% 61.6ms +/- 8.8% significant
morph: 3.86x as fast 469.6ms +/- 6.5% 121.6ms +/- 21.7% significant
raytrace: 9.08x as fast 697.2ms +/- 4.1% 76.8ms +/- 18.2% significant

access: 16.3x as fast 2847.8ms +/- 1.7% 174.6ms +/- 11.1% significant
binary-trees: 49.4x as fast 504.2ms +/- 8.6% 10.2ms +/- 5.5% significant
fannkuch: 18.5x as fast 1219.8ms +/- 6.5% 65.8ms +/- 29.0% significant
nbody: 11.6x as fast 712.0ms +/- 6.8% 61.2ms +/- 14.0% significant
nsieve: 11.0x as fast 411.8ms +/- 14.2% 37.4ms +/- 17.0% significant

bitops: 19.0x as fast 2268.8ms +/- 6.8% 119.2ms +/- 11.7% significant
3bit-bits-in-byte: 37.9x as fast 325.6ms +/- 11.3% 8.6ms +/- 7.9% significant
bits-in-byte: 24.9x as fast 493.4ms +/- 8.0% 19.8ms +/- 19.6% significant
bitwise-and: 27.0x as fast 913.8ms +/- 13.5% 33.8ms +/- 9.5% significant
nsieve-bits: 9.40x as fast 536.0ms +/- 4.3% 57.0ms +/- 19.9% significant

controlflow: 78.6x as fast 440.4ms +/- 7.2% 5.6ms +/- 12.2% significant
recursive: 78.6x as fast 440.4ms +/- 7.2% 5.6ms +/- 12.2% significant

crypto: 10.8x as fast 1168.0ms +/- 5.7% 108.6ms +/- 12.5% significant
aes: 12.4x as fast 528.4ms +/- 6.3% 42.6ms +/- 11.4% significant
md5: 7.96x as fast 315.4ms +/- 8.8% 39.6ms +/- 33.3% significant
sha1: 12.3x as fast 324.2ms +/- 4.8% 26.4ms +/- 9.8% significant

date: 1.75x as fast 1620.4ms +/- 1.9% 928.4ms +/- 6.6% significant
format-tofte: 1.53x as fast 716.2ms +/- 3.1% 468.6ms +/- 6.0% significant
format-xparb: 1.97x as fast 904.2ms +/- 3.8% 459.8ms +/- 9.9% significant

math: 6.38x as fast 1524.8ms +/- 2.9% 239.0ms +/- 15.2% significant
cordic: 4.68x as fast 661.0ms +/- 2.9% 141.2ms +/- 27.4% significant
partial-sums: 5.74x as fast 426.0ms +/- 5.7% 74.2ms +/- 18.6% significant
spectral-norm: 18.6x as fast 437.8ms +/- 2.8% 23.6ms +/- 19.9% significant

regexp: *1.06x as slow* 724.8ms +/- 3.0% 767.2ms +/- 3.3% significant
dna: *1.06x as slow* 724.8ms +/- 3.0% 767.2ms +/- 3.3% significant

string: 4.57x as fast 5092.4ms +/- 2.0% 1113.6ms +/- 5.4% significant
base64: 16.0x as fast 2232.8ms +/- 4.5% 139.6ms +/- 20.7% significant
fasta: 8.52x as fast 994.8ms +/- 3.1% 116.8ms +/- 7.5% significant
tagcloud: 1.80x as fast 579.0ms +/- 4.3% 321.4ms +/- 8.5% significant
unpack-code: 1.78x as fast 698.2ms +/- 3.5% 391.2ms +/- 3.3% significant
validate-input: 4.06x as fast 587.6ms +/- 6.2% 144.6ms +/- 10.4% significant

You can see that JavaScript performance is the major advantage to Chrome.  They claimed in their comic intro that using multiple processes would result in less memory usage, but I didn't think so -- that woulden't make any sense.  The figure next is a table from Google's own memory tool.  I opened all of the same websites on Chrome and Firefox to see what the memory footprint really looked like.  Keep in mind that Chrome base install is a very basic browser!  My Firefox has a TON of useless plug-ins and themes installed and it still beat Chrome quite handily!

Memory (Google vs Firefox 3*)



Virtual memory 
154,844k 5,816k 160,660k 287,304k 107,336k
Firefox 3.0.1
132,572k 11,552k 144,124k 129,752k 11,844k


MemoryVirtual memory
37564k 21116k 58680k 43728k 26796k
Tab 2
Gmail - Inbox (9) -
27616k 2660k 30276k 44416k 9816k
Tab 3
CUEgle 3
8472k 2304k 10776k 32484k 9816k
Shockwave Flash
56276k 10032k 66308k 94536k 11828k
Tab 9
MSN Video
10872k 3376k 14248k 25140k 9816k
Tab 10
7736k 7380k 15116k 10396k 9816k
Tab 14
Understanding User-Agent Strings
2668k 1736k 4404k 12256k 9816k
Tab 17
Windows Live Hotmail
2304k 1624k 3928k 12540k 9816k
Tab 20
SunSpider JavaScript Benchmark Results
1336k 2120k 3456k 11808k 9816k
Tab 25 (diagnostics)
About Memory
8908k 3428k 12336k 9644k 9816k
Σ 163752k 219528k 296948k

I haven't decided wither I will use this browser on a daily basis. Probably not -- no compelling reason to switch, but I can see that some will really like this browser. Perhaps once I get used to the idea of Google making a browser and have IE tick me off once more I'd be in a different place, but for now I kind of don't want a Google Browser.