Virtual Machine Performance on a Laptop

So, now that I’ve had an opportunity to run my virtual machines on my new E6400 laptop, I thought I’d share what I’ve learned. But, first, a bit about the other piece of hardware that I use with my virtual machines:

Because virtual machines are notoriously slow, you want to do everything you can to help them out. Probably the most important thing you can do is to host them on a different physical drive from your operating system. Less contention for the disk means faster disk access. It also helps to get the fastest drive possible, since virtual hard drives are nothing more than incredibly large files that you will inevitably want to copy and move around.

So, for years now, I’ve carried around a small (2.5”/60GB), fast (7,200RPM), USB 2.0 (440Mb/sec) drive to host my virtual machines. It has worked great: it’s portable, it’s fast, and I can plug it into virtually any computer and be up and running in minutes.

Sure, a larger drive would be better. 60GB was the largest 7200RPM 2.5” drive at the time I bought mine. Now, you can get 300GB+ at 7200RPM for just a couple hundred dollars.

A faster drive would also be nice. 7200RPM was the fastest 2.5” drive on the market at the time I was buying. Now, you can get 2.5” 10,000RPM drives. And, you can even get 15,000RPM drives, if you don’t mind lugging around a 3.5” drive and another power brick.

Finally, a faster pipe would really help. When I bought my drive, USB 2.0 was the fastest ubiquitous connector out there. Now, you can often find FireWire 800 ports (at 800Mb/sec). And, low-and-behold, my new E6400 has an eSATA port (at 3Gb/sec!).

So, needless to say, I had to try out the SATA port. Long story short: IT SCREAMS! It is easily 5-10x faster than the USB connection. In fact, it’s so fast, I defy anyone to tell me whether or not they’re running the host OS (on the metal, as they say), or the guest OS (virtually)! Don’t believe me? Come over and see for yourself!

I am a convert! I will not be going back to USB any time soon!

Virtual Machines

A professor of mine once told me that anything software could do, hardware could do faster. It turns out that anything hardware can do, software can do, too!

What is a virtual machine?

A virtual machine is a fake computer running a real operating system within a window on another real operating system running on a real computer. Confused? Think of it this way…

Imagine booting your PC, logging in, and running Microsoft Word. Word launches in a new window, just as you would expect. Now, imagine if you could run Windows in a window instead of Microsoft Word. That’s a virtual machine.

Why use virtual machines?

There are many, many reasons to run virtual machines. But, all of them boil down to the same underlying reason: Money.

For example, suppose I’m a web developer. (Imagine that! Me! A web developer! How chic!) And, suppose I’d like to test my new website in all the major browsers, starting with Internet Explorer and Firefox. I can’t configure one machine with all the different versions of all the different browsers. They’re not compatible with each other. (Actually, they’re not compatible with themselves. But, let’s not go there.)

I could go out and buy a bunch of real PCs; install one browser on each; and, run my tests on each machine. But, even with very inexpensive machines, I’d be looking at several thousand dollars just to setup my test environment. (Ouch!) Or…

I could create a bunch of virtual PCs; install one browser on each; and, run my tests on these fake machines on a single real machine. Total cost for additional hardware? ZERO DOLLARS. (Cha-ching!)

How can I get started with virtual machines?

Funny you should ask! I was just about to mention that Microsoft Virtual PC is a free product that lets you create all the virtual machines you can imagine. There are a couple of caveats, though. (There are always caveats.)

First: Each virtual machine you create will need an operating system. And, each operating system you install needs to be licensed legally. (So, now you see why Microsoft is giving away Virtual PC! It’s like the razor. Windows is the razor blade!) So, an enterprise license for Windows, or an MSDN license are probably the safest ways to ensure that your virtual machines are all legal.

And, second: If you think Windows is slow on your real computer, try running Windows on top of Windows on top of your real computer! Virtual machines are notoriously slow. It takes quite a bit of real hardware in order to brute force a virtual machine into performing like an adequate real machine. So, virtualization is only for those of us with very strong machines. My desktop (an Optiplex 7400) handles the load fine. I’ll be experimenting with my new developer laptop (an E6400) soon. I’ll let you know how that goes.

As always, ping me or comment on this post if you have questions…

Take my advice: Use a single field to represent complex numbers!

When creating data entry applications, it is often tempting to represent complex numbers – such as Social Security numbers and telephone numbers – as multiple text boxes, like this:

image

The thought is that this simplifies data entry by allowing the end-user to focus on the numbers, not the formatting. Sounds good. But, I’m here to tell you that I have been down this road. It is paved with good intentions. But, you do not want to end up where it will take you.

For brevity, let’s just cut to my preferred solution:

  1. Use a single text box to represent the complex number
  2. Use a RequiredFieldValidator to ensure that users don’t skip the field (if necessary)
    • With multiple fields, you’d have to write your own custom validator control.
  3. Use a RegularExpressionValidator to ensure that the data is in an acceptable format
    • You could split the regular expression into three shorter regular expressions, I suppose. But, why would you want to edit the working regex you grabbed off the Intertubes? That would require you to understand the thing!

The advantages of this approach are:

  1. Users can enter raw numbers or formatted text (which helps when the user is trying to copy/paste)
  2. Users can copy/paste in one shot
  3. Users don’t have to tab between extra fields
  4. Users can use Backspace and arrow keys to fix typos (without tabbing/clicking around)
  5. Programmers don’t have to write code to parse/concatenate the fields
  6. Programmers don’t have to write custom validator code

Everybody wins! And, just to prove how simple it is, here’s the code for Social Security Numbers and North American telephone numbers:

Social Security Numbers

<asp:Label ID="SSNLabel" runat="server" Text="SSN:"/>
<asp:TextBox ID="SSNTextBox" runat="server"/>
<asp:RequiredFieldValidator runat="server" Display="Dynamic"
  ID="SSNRequiredFieldValidator" 
  ControlToValidate="SSNTextBox" 
  ErrorMessage="SSN is a required field."/>
<asp:RegularExpressionValidator runat="server" Display="Dynamic"
  ID="SSNRegularExpressionValidator" 
  ControlToValidate="SSNTextBox" 
  ErrorMessage="Please enter a valid SSN." 
  ValidationExpression="^\d{3}[- ]?\d{2}[- ]?\d{4}$"/>

Note: The regular expression above allows formatted SSNs as well as raw numbers. Spaces and hyphens are considered acceptable delimiters, but are not required.

North American Telephone Numbers

<asp:Label ID="PhoneNumberLabel" runat="server" Text="Phone Number:"/>
<asp:TextBox ID="PhoneNumberTextBox" runat="server"/>
<asp:RequiredFieldValidator runat="server" Display="Dynamic"
  ID="PhoneNumberRequiredFieldValidator" 
  ControlToValidate="PhoneNumberTextBox" 
  ErrorMessage="Phone number is a required field."/>
<asp:RegularExpressionValidator runat="server" Display="Dynamic"
  ID="PhoneNumberRegularExpressionValidator" 
  ControlToValidate="PhoneNumberTextBox" 
  ErrorMessage="Please enter a valid phone number, including area code." 
  ValidationExpression="^(?:\([2-9]\d{2}\)\ ?|[2-9]\d{2}[- ]?)[2-9]\d{2}[- ]?\d{4}$"/>

Note: The North American Numbering Plan (NANP) specifies that the area code and prefix must not begin with 0 or 1, for obvious reasons. The regular expression above validates this. It also handles complex formats as well as raw numbers. Spaces and hyphens are considered acceptable delimiters, but are not required. The area code may or may not be wrapped in parentheses, and may or may not include a space (but not a hyphen) after the trailing parenthesis.

Email Productivity

I manage email differently that just about everyone I know. I find my method to be tremendously productive. Maybe you will, too.

My system is adapted from Inbox Zero, which is based on Getting Things Done. It works like this:

1. I organize my Inbox with categories, rather than folders

All mail lands in my Inbox, and that’s where it stays. There are currently 5708 messages in my Inbox. If I need to go back and find a message, I use the terrific search mechanism built into Outlook 2007. This alone eliminates hours upon hours of filing messages into an appropriate folder structure. Plus, search is much quicker than trying to remember where I put something.

A rule deletes any categories and flags on every incoming message. (You’ll see why in a minute.) And, more rules categorize each message as follows:

  • imagePersonal
    • From my wife
    • Marked as Personal
  • Important
    • Marked as High Importance
    • From my boss
    • From members of my team
  • Interesting
    • From interesting distribution lists
    • From upper management
  • Neither Important Nor Interesting
    • Marked as Low Importance
    • Everything else

This allows me to focus on the most important email first, saving me time weeding through my messages.

2. I track whether or not I’ve dealt with a message with flags, rather than Read/Unread

Messages without a flag (including all incoming messages) appear in a search folder I created and named “Triage.” These messages need my attention. So, I start here, whenever I check email. My goal is to empty this folder every time I view it by taking one of the following actions for every message: (This is from Inbox Zero.)

  • imageDelete
    • Do I really need to keep this?
    • I’m very aggressive about this, especially in the “Neither” category.
  • Delegate
    • Can someone else handle this better than me?
    • Flag message for follow up on a specific day
  • Respond
    • If responding takes less than 2 minutes.
    • Flag message as complete
  • Do
    • If action takes less than 2 minutes.
    • Flag message as complete
  • Defer
    • If responding/acting would take more than 2 minutes.
    • Flag message for follow up on a specific day (which could be Today)

I spend almost zero time in my Inbox. I spend approximately 15-30 minutes a day in this folder. You’ll be surprised how much mail lands in that “Neither” bucket and gets deleted immediately!

3. I manage any “deferred” mail as tasks, rather than email

image

Messages flagged for follow up automatically appear in the Outlook To-Do List along with other active tasks. So, after I empty my Triage folder, I head over here to focus on completing tasks (including those emails I deferred above). And, since I’m no longer in the Mail portion of Outlook, I won’t be distracted by incoming messages. (I also turn off all the new mail messages and sounds for the same reason.)

This reduces the time I spend switching tasks significantly. I stay focused and things get done.

In summary

I’ve found this to be an extremely productive email management system. Though, it does require a bit of discipline. Staying focused always does.

Note: As I mentioned above, I use Outlook 2007. I highly recommend that you upgrade, if you haven’t already. The new search mechanism is worth the upgrade alone!

Applying the Single Responsibility Principle

I reviewed a bit of code today that presents an excellent opportunity to discuss a big difference between procedural and object-oriented code. Here’s the code I reviewed:
private void DisplayCoBrandedImages()
{
    string imageUrl = "~/images/cobrand/" + ContractId + ".gif"; 
    bool isCoBranded = File.Exists (Server.MapPath(imageUrl)); 
    bool isGroup = (Page.Category & DisplayCategory.GroupLevel) == 
        Page.Category;

    if (isGroup)
    { 
        imageUrl = "~/images/cobrand/GroupOnlineLogo.gif";
    }

    _brandedImage.Visible = isCoBranded || isGroup; 
    _brandedImage.ImageUrl = imageUrl;
}
This is a good example of procedural code, where a single method has multiple responsibilities. In this case, the method DisplayCoBrandedImages is:
  • Determining if the page should be co-branded;
  • Determining if the page is a group page;
  • Determining which image to display; and,
  • Setting the properties of the image control.
In object-oriented programming, however, we strive to follow the Single Responsibility Principle, which states that code should only have one reason to change. But, any of the tasks mentioned above might change independently of the other tasks. So, if I were to refactor this code into a more object-oriented structure, I would expect to see a different method (or property) handling each of those items above, like this:
private void DisplayCoBrandedImages()
{ 
    _brandedImage.Visisble = IsCoBranded || IsGroup; 
    _brandedImage.ImageUrl = GetImageUrl(); 
}

private bool IsCoBranded
{
    get { return File.Exists(ImageUrl); }
}

private bool IsGroup
{ 
    get { return (Page.Category & DisplayCategory.GroupLevel) == 
        Page.Category; }
}

private string ImageUrl
{
    get
    {
        if (IsGroup)
            return "~/images/cobrand/GroupOnlineLogo.gif";
        else
            return "~/images/cobrand/" + ContractId + ".gif";
    } 
}
Now, the primary method (DisplayCoBrandedImages) is only responsible for setting the attributes of the image control. It relies on helper methods (or, as in this case, properties) to perform the other, subordinate tasks. The resulting code, while longer, is easier to understand, because each method is only doing one thing.

Coding Standards

I wish I could remember who told me this…

It does not matter which side of the road we drive on, as long as we all drive on the same side as everyone else.

My Marick Test Matrix

I introduced the Marick Test Matrix in the previous post. As much as I like it and have come to rely on it. One thing has always bugged me about the matrix: The terms Brian used to describe his horizontal axis seem, IMHO, obtuse. Instead, I prefer these simpler terms:

  • Support Programming = Define Requirements
  • Critique Product = Identify Defects

Given those changes, here’s my updated matrix:

I prefer these axes because now I can refer to each quadrant by a simple name:

  • Business/Requirements
  • Business/Defects
  • Technology/Requirements
  • Technology/Defects