Simple(r) Hyper-V Networking on Windows 8


A while ago I wrote a post on setting up HyperV networking where I basically bridged all networks to the guests and let them worry about which one they needed to use.

Albeit a little complicated it worked pretty good. However sometimes the guests messed it up and couldn’t figure which network to use for the AD and DNS and also the Default Gateway setting could be stuck on the “wrong” network.

Therefore here is a new and vastly better approach J – using only one internal network and the windows Internet Connection Sharing (ICS).

(This is essentially a “NATing” approach where the other was primarily a “Bridging”)

Caution: The two network configurations are inherently incompatible; you should choose only one to go for.

The Goal (still…)

Is quite simply that I want my VMs to just work seamless with my Host machine and whatever network connection I’m using and – in my case – a guest AD.

This used to be really simple with VMWare Workstation but after converting my machines to Hyper-V there is a catch or two.

This post covers:

Part 1: Simple Network setup, if you need a simple fix this is it

Part 2: Automatic network sharing, this is what makes it shine

Part 3: Advanced stuff for the last 10% of needs

Note that this applies to a mobile working scenario where I run everything on a laptop and it frequently changes whether I’m using a wired, wifi or mobile net.

The Environment

I do SharePoint development and this post is written in that context, however it should all be generally applicable to Hyper-V.

My local Hyper-V (SharePoint Dev) environment (simplified) consists of two guests:

  • An AD server that should not communicate outside my box
  • A SharePoint server that need to communicate with my host, the guest AD and generally networking

In addition I need to connect with Remote Desktop to the guest machines with the host (the Hyper-V console is useless for all but boot and network configurations).

Part 1: Basic Network

We’ll set the network up as:

The Hyper-V Network Settings

The steps to configure the network on the host are:

  1. Create an internal switch for the connection between host and virtual machines (and in my environment between the AD and SharePoint server)
    1. Name it appropriately (I just like that)
  2. Go to your host and select the currently active network connection, choose Properties, Sharing and choose the HyperV switch
    1. When your active network connection changes, you’ll have to share the new connection (there can be only one)

That’s it for the host.

The Guest Configuration

We need to configure the guests themselves. Connect to each one using the Hyper-V console:

  1. For the AD guest server (internal communication only) assign the ip address 192.168.137.10 (pick the last number as you like) – there should only by one network adapter
    1. Set the default gateway to 192.168.137.1 (which is your host) and DNS to 127.0.0.1
    2. When you change the IP address for an AD server you need to restart it so that the DNS is properly updated
    3. Reboot the AD
  2. For the guests that need network access:
    1. Assign the chosen IP to the internal network, in my case, 192.168.137.20 (a unique one for each guest), use 192.168.137.1 as default gateway, use 192.168.137.10 (your AD) as your single DNS
  3. Test it, on each guest:
    1. Lookup an AD user or two – do you have a proper connection between the guests?
    2. Ping 192.168.137.1 – does your gateway respond?
      If not have a close look at ICS, google various troubleshooting tips
    3. Ping 8.8.8.8 – do you have basic external network?
    4. Ping google.com – do you have DNS resolution working?
      In case of DNS lookup problems: Have a look at your DNS and possibly remove any DNS forwarders that you may have (google it!)
    5. Browse a site – is the firewall open?

That’s it for the guests!

RDP Access

Finally you’ll want to access the guests through RDP so stuff like copy/paste and fullscreen works. You can of course use whatever RDP manager you prefer, here I’ve just used the standard one.

Make a connection for each Guest access and save it somewhere (Desktop?).

Run the command “mstsc” and setup the options you like and save the Connection. In particular enable “Clipboard” and “Drives” in the “Local Resources” tab. That will enable you to copy/paste both text and files between the guest and host.

In my case:

Note that I have added “sp2010” in my host file as 192.168.137.10. You can also use just the IP.

Part 2: Making it Shine – Automate it

Now for the fun part. I want it all to to just work.

No fiddling around with sharing this or that network adapter, just make the one I’m using for the host the one that is shared.

Using PowerShell and the system task scheduler it’s doable.

To install:

  1. Download and unzip this file, e.g. to C:\AutoNetworkSharing
  2. Right click the dll and ps1 file, choose properties and “unblock” them
  3. Test 1:
    1. Start an administrative shell
    2. Execute “powershell.exe –File c:\AutoNetworkSharing\AutoSwitch.ps1”
    3. Watch the printed output. It should share your active network connection with your HyperV network adapter and write what it does in the process
    4. Run it again and make sure that this time it detects that it need not change the sharing properties
  4. Go to your Task Scheduler
  5. I like to create a new folder,e.g.”MyCustomTasks” to keep track of what I’m doing:

  6. Click “Import Task”
  7. Choose the “SwitchNetworkSharingScheduledTask.xml” file (in the zip)
  8. On the “Create Task” dialog, go to the Actions tab and correct the file name parameter to match your location:
  9. Have a look at the “Triggers” tab, here is the magic that ensures that this task is fired whenever your network connection changes
  10. Test 2:
    1. Enable and disable your network adatpers to see the “Sharing” label move around as you do so. It should take no more than 10 seconds to see the sharing property change
    2. If it doesn’t work have a look in the history tab on the scheduled task to see whether the task starts or if’s the actual script that fails

One caveat: The HyperV network will jump briefly when the network changes, so your RDP session will briefly freeze.

The actual script is mostly about deep diving into the WMI and looks like this (Note: Do not copy/paste this directly. Quotes and dashes will likely be wrong, take it from the zip file):

Import-Module ( join-path (Split-Path -Parent $MyInvocation.MyCommand.Path) “IcsManagerLibrary.dll” )

#Fetch the active adapter and Hyperv NIC from WMI
$activeAdapters = Get-WmiObject win32_networkadapterconfiguration -Filter ‘ipenabled = “true”‘

#CHANGE THIS LINE IF you need to handle multiple HyperV nics to you own rules
$hypervNics = $activeAdapters |? { $_.ServiceName -eq     ‘VMSMP’ }

if( @($hypervNics).Count -ne 1 ){
    Write-Error     “Cannot auto switch, found $(@($hypervNics).Count) hyper-V NICs”
    return
}

#Get the adapters with network connectivity
$activeNetworks = Get-WmiObject -Class Win32_IP4RouteTable -Filter “Destination=’0.0.0.0′” |% { Get-WmiObject win32_networkadapterconfiguration -Filter     “ipenabled=’true’ and InterfaceIndex=$($_.InterFaceIndex)” }
if( @($activeNetworks).Count -ne 1){
    Write-Warning     “Multiple active NICs found, picking one at random”
    $activeNetworks = $activeNetworks[0]
}
    
#Get the “real” NIC name, required by the cmdlet
$hyperVTypedNIC =  Get-WmiObject -Class Win32_NetworkAdapter -filter “DeviceID = $($hyperVNics.Index)”
$activeTypedNIC =  Get-WmiObject -Class Win32_NetworkAdapter -filter “DeviceID = $($activeNetworks.Index)”

#Retrieve what is shared by ICS now (if anything)
$sharedPublicNetwork =  Get-WmiObject -Class HNet_ConnectionProperties -Namespace “ROOT\microsoft\homenet” -Filter ‘IsIcsPublic = “true”‘
$sharedPrivateNetwork =  Get-WmiObject -Class HNet_ConnectionProperties -Namespace “ROOT\microsoft\homenet” -Filter ‘IsIcsPrivate = “true”‘

#Do a test to see if the selected NIC to be shared is already shared (then do nothing)
if( $sharedPublicNetwork -and $sharedPublicNetwork.Connection -match $activeTypedNIC.GUID -and $sharedPrivateNetwork -and $sharedPrivateNetwork.Connection -match $hyperVTypedNIC.GUID){
    
    Write-host     “Already shared ‘$($activeTypedNIC.NetConnectionID)’. Skipping.”
    return
}
else{
    Write-host     “Sharing ‘$($activeTypedNIC.NetConnectionID)’ to ‘$($hyperVTypedNIC.NetConnectionID)'”
    Enable-ics -Shared_connection $activeTypedNIC.NetConnectionID -Home_connection $hyperVTypedNIC.NetConnectionID -force $true      
Write-host     “Done”
}

It assumes that there is only enabled HyperV network adapter (if not change the marked line) and it will pick a random active internet connection to share if there is more than one.

Note: I’m dependent on the “ICSManager” module developed by Utapyngo for handling the ICS part.

Part 3: Going advanced

Well sometimes you need a bit more J

Here are the few things that I found myself needing.

Multiple subnets

If you have more than one HyperV teams, e.g. multiple AD controllers that should be kept separate, you need to split the network.

As the ICS service will reset your hosts’ HyperV adapter to an ip of 192.168.137.1 and reset all submask and DNS settings, you shouldn’t mess with them.

On the other hand it is quite possible (and easy) to separate your teams by specifying smaller submasks in the guests, i.e. assign the submask 255.255.255.128 to all guests and assign

  • AD in team 1 an IP of 192.168.137.10
  • AD in team 2 an IP of 192.168.137.130

And subsequent guests IPs within their network range. Keep the default gateway as 192.168.137.1 for all guests.

Multiple HyperV networks and bridges

In the case of multiple HyperV cards you will need to modify the PowerShell script file, to select the proper HyperV card to share with. Simple give your desired HyperV adapter an easy readable name in the host.

Perhaps just hardcode the HyperV adapter name in call to the “Enable-ICS” commandlet.

Happy networking 🙂

Spring Cleaning Your Dev Box


After some time your dev box ends up looking like a well-used tool shed complete with unused tools and cobwebs in the corners.

While it’s quick and easy to get rid of half the icons on your desktop and delete droves of temporary working files – I always end up returning to a few well used scripts to get my much needed disk space back as well as a cleaner and faster box.

Often the trigger is exhausted disk space.

These are the scripts I always end up using.

Delete old site collections

If you are making site definitions (or web templates) you’ll likely end up with tons of small test site collections over time. I often use scripts to create them named after the current time.

To clean that all up I use the PS script (run in the SharePoint Administrative Console):

    get-spsite http://* -limit all |? { $_.Url -Match "http://.*/" -and $_.LastContentModifiedDate -gt [DateTime]::Today.AddMonths(-2)} | remove-spsite

In human terms: “Delete every site collection that is not a root site collection and that have not been modified within the last two months”. Phew.

Do NOT run this in production.

Set Simple SQL Recovery Mode

Next I ensure that all my local databases run in simple recovery mode, i.e. avoid huge transactions logs that need to truncated once in a while.

I nicked this script somewhere in google (likely here) (updated Jun 27: Fixed – my angle brackets had been eaten):

USE MASTER
declare
	@isql varchar(2000),
	@dbname varchar(64)
	
	declare c1 cursor for select name from master..sysdatabases where name not in ('master','model','msdb','tempdb')
	open c1
	fetch next from c1 into @dbname
	While @@fetch_status <> -1
		begin
		select @isql = 'ALTER DATABASE [@dbname] SET AUTO_CLOSE OFF'
		select @isql = replace(@isql,'@dbname',@dbname)
		print @isql
		exec(@isql)
		select @isql = 'ALTER DATABASE [@dbname] SET RECOVERY SIMPLE'
		select @isql = replace(@isql,'@dbname',@dbname)
		print @isql
		exec(@isql)
		select @isql='USE [@dbname] checkpoint'
		select @isql = replace(@isql,'@dbname',@dbname)
		print @isql
		exec(@isql)
		
		fetch next from c1 into @dbname
		end
	close c1
	deallocate c1

Run it within the SQL Server Management Studio.

Note that it is likely that the script will report a few minor errors if some DBs are detached/offline. Never mind.

Shrink DBs

Finally save some much needed space by shrinking the DB files. After site collection deletions and recovery mode changes there are likely a lot of space to be freed within the DB files.

This script will try to shrink all the DB files (I think I got it from here):

DROP TABLE #CommandQueue

CREATE TABLE #CommandQueue
(
    ID INT IDENTITY ( 1, 1 )
    , SqlStatement VARCHAR(1000)
)

INSERT INTO    #CommandQueue
(
    SqlStatement
)
SELECT
    'USE [' + A.name + '] DBCC SHRINKFILE (N''' + B.name + ''' , 1)'
FROM
    sys.databases A
    INNER JOIN sys.master_files B
    ON A.database_id = B.database_id
WHERE
    A.name NOT IN ( 'master', 'model', 'msdb', 'tempdb' )

DECLARE @id INT

select * from #CommandQueue

SELECT @id = MIN(ID)
FROM #CommandQueue

WHILE @id IS NOT NULL
BEGIN
    DECLARE @sqlStatement VARCHAR(1000)
    
    SELECT
        @sqlStatement = SqlStatement
    FROM
        #CommandQueue
    WHERE
        ID = @id

    PRINT 'Executing ''' + @sqlStatement + '''...'

    EXEC (@sqlStatement)

    DELETE FROM #CommandQueue
    WHERE ID = @id

    SELECT @id = MIN(ID)
    FROM #CommandQueue
END

Again expect some errors, inspect and accept them 😉

Expand the Disk?

If the three steps above didn’t free enough space for you, the solution often is to just expand the VHDs on your virtual machines.

It’s a fairly easy process in both VMWare and HyperV it only requires you to turn off the VM, remove any snapshots, and expand the disk using the wizard for it. This will only expand the VHD; your partitions will not grow, so you need to do that next.

You can use the disk management tool for it – however I find it cumbersome. Especially if it is the system disk you’re expanding it is awkward. I prefer to use GPartED, which is a very nice linux partition editor. It is a downloadable iso that is a breeze to boot into and expand the partition whether it is the system or not.

One note: In a typical Linux way you are asked all sorts of questions at boot; just hit return at every one of them. Who cares about the keyboard layout for a GUI program with big buttons anyway?

It looks something like this:

(Note: Before using this program make sure that you close down the VM nicely from the guest)

Easy.

Quick tip: Handy Scripts for Local Hyper-V Management


Here is a quick post with a small script that I find incredibly handy for managing my local Hyper-V machines (on windows 8).

It simply ensures what set of VMs are running at a given time – attach that to a shortcut on the desktop and it saves me 3 minutes every day; I find it useful.

Why? Quite often, I need to switch from one set of VMs to another for different tasks (VMWare term is “teams”) e.g. switching between SP2010 and SP2013 development. Sometimes just turn them off if I need the resources for something else.

Normally you just go into Hyper-V manager and start/stop the relevant VMs. Automating that was quite simple and painless – the download is here.

  1. I have one PowerShell script (SetRunningVMs.ps1) that handles the VM management and then a couple of batch files for executing that script with proper parameters. The script is:
    <#
    .SYNOPSIS
    This is a simple Powershell script that adjust what VMs are running on the local Hyper-V host.
    
    .DESCRIPTION
    This script will start/resume the requested VMs and suspend all other VMs to give you maximum power and make it easy to switch from one
    development task to another, i.e. switch teams.
    
    .EXAMPLE
    Make sure that only the dev1 and ad01 machines are running:
    ./SetRunningVMs.ps1 'dev1' 'ad01'
    
    Stop all VMs (no arguments)
    ./SetRunningVMs.ps1 
    
    .NOTES
    Requires admin rights to run. Start using admin shell or use one of the provided batch files.
    Pauses on error.
    
    .LINK
    https://soerennielsen.wordpress.com
    #>
    
    param( [Parameter(ValueFromRemainingArguments=$true)][string[]] $allowedVMs = @() )
    
    try{
        get-vm |? { $_.State -eq "Running" -and $allowedVMs -notcontains $_.Name } |% { Write "Saving $($_.Name)"; Save-VM $_.Name }
    
        get-vm |? { $_.State -ne "Running" -and $allowedVMs -contains $_.Name } |% { Write "Starting $($_.Name)"; Start-VM $_.Name }
    
        write "SetRunningVMs succesfully done"
    }
    catch{
        Write-Error "Oops, error:" $_
        pause
    }

    I assume that the PowerShell Hyper-V module is loaded; it has always been the case in my tests.

  2. I have a number of batch files for easily executing the script, one for turning off (suspend) all VMs, one for a SP2010 team and one for the SP2013 team. It’s a one-liner bat file that will work with both PowerShell 2 and 3, with or without UAC.

    To Start my SP2010 team (StartSP2010Team.bat):

    powershell -noprofile -command “&{ start-process powershell -ArgumentList ‘-noprofile -file %~dp0SetRunningVMs.ps1 \”AD01\” \”Dev1\”‘ -verb RunAs}”

    (where you replace the bold VM names above with your own)

    To start my SP2013 team (StartSP2013Team.bat)

    powershell -noprofile -command “&{ start-process powershell -ArgumentList ‘-noprofile -file %~dp0SetRunningVMs.ps1 \”AD02\” \”SP2013\”‘ -verb RunAs}”

    To stop all VMs

    powershell -noprofile -command “&{ start-process powershell -ArgumentList ‘-noprofile -file %~dp0\SetRunningVMs.ps1’ -verb RunAs}”

If you have UAC enabled (as I do) you will be prompted, otherwise it will just suspend/resume the relevant VMs.

It took about two hours to write the scripts, where the hardest part was getting the batch files properly in shape with escape characters and UAC.

You gotta love PowerShell 😉

How to Setup Hyper-V Networking on Windows 8


[Update 7. oct. 2013: Check out the follow up post here – it shows a better way]

It seems that the best way to setup networking in Hyper-V on a Windows 8 machine is quite far from obvious. I have spent some time getting this working as it should, so read on…

The Goal

Is quite simply that I want my VMs to just work seamless with my Host machine and whatever network connection I’m using and – in my case – a guest AD.

This used to be really simple with VMWare Workstation but after converting my machines to Hyper-V there is a catch or two.

Note that this applies to a mobile working scenario where I run everything on a laptop and it frequently changes whether I’m using a wired, wifi or mobile net.

The Environment

I do SharePoint development and this post is written in that context, however it should all be generally applicable to Hyper-V.

My local Hyper-V (SharePoint Dev) environment consists of two guests:

  • An AD server that should not communicate outside my box
  • A SharePoint server that need to communicate with my host, the guest AD and generally networking

In addition I need to connect with Remote Desktop to the guest machines with the host (the Hyper-V console is useless for all but boot and network configurations).

The Hyper-V Network Settings

The steps to configure the network on the host are:

  1. Create an external virtual switch for each of your external network adapters in the Hyper-V manager
  2. Create an internal switch for the connection between host and virtual machines (and in my environment between the AD and SharePoint server)
  3. A catch: In my case the mobile adapter was not selectable (not sure if that is always the case) when I create a virtual switch.

    In that case create an internal switch (name it “External” something as it will be configured for that)

    1. Go to your Network Connections, choose your mobile adapter, Sharing and choose to share the connection with the newly created virtual switch (see the picture below)

  4. Name them all appropriately otherwise you’ll regularly end up being confused 😉

    After that your Hyper-V settings look something like this:

  5. Finally you need to pick some static IP addresses for your internal network as you’ll want the host to communicate with the guests and the guests to be able to talk to each other. There is no DHCP on the internal switch (would be a reasonable feature request for the next version of Hyper-V). I this case I picked 192.168.10.2 for my host:

  6. If you want to be able to refer to your guest machines by their names you need to add a couple of entries to your hosts host file 😉 Edit the file C:\Windows\System32\Drivers\etc\hosts and add a line for each guest

    I picked 192.168.10.10 for my AD guest and 192.168.10.20 for my SharePoint guest:

The Guest Configuration

First of all you need to connect the virtual switches appropriately to your guests in the Hyper-V Manager:

  • For the guests that only need to communicate internally connect only the internal switch
  • For the guests that need full internet access connect all the switches

Finally we need to configure the guests themselves. Connect to each one using the Hyper-V console:

  1. For the AD guest server (internal communication only) assign the ip address 192.168.10.10 (the one picked above) – there should only by one network adapter
    1. When you change the IP address for an AD server you also need to change the address appropriately in the DNS manager. Simply start the DNS manager and click through the nodes and change all IP addresses to the new address
    2. If you have a registration for other clients (other guest machines) update those records to the IP you chose for them
    3. Reboot the guest
  2. For the guests that need network access
    1. Assign the chosen IP to the internal network, in my case, 192.168.10.20
    2. Add two lines to the guest machines host file to make sure that the AD guest server can be found:

      “192.168.10.10 ad01” and “192.168.10.10 ad01.domain.local” where the second is the FQDN of the AD server

    3. You should now have a number of network adapters that are connected to the host’s physical adapters and it will automatically figure out which ones are connected and use whichever is appropriate. I recommend that you named them appropriately in the guest.
    4. Catch (do not skip this): I did however find that it was unable to correctly figure out whether the mobile adapter was connected or not (likely because I created it as an internal switch). I fixed that by prioritizing the mobile network connection last so it will only use the mobile if all others fail. You just need to set the “network metric” to something high (high is lowest priority), follow the process in the picture below

That’s it for the guests!

RDP Access

Finally you’ll want to access the guests through RDP so stuff like copy/paste and fullscreen works. You can of course use whatever RDP manager you prefer, here I’ve just used the standard one.

Make a connection for each Guest access and save it somewhere (Desktop?).

Run the command “mstsc” and setup the options you like and save the Connection. In particular enable “Clipboard” and “Drives” in the “Local Resources” tab. That will enable you to copy/paste both text and files between the guest and host. Will also grant access to the host’s drives.

In my case:

Going for the Advanced Mode?

While the settings above work fine; there is always room for improvement.

I think it would be better to install a third machine as a firewall/router so the firewall handled all external connections and boxed in the essentially rogue guest machines. They really only need to communicate externally on port 80/443.

I will give m0n0all a go soon 🙂

Troubleshooting

Once in a while something goes wrong. Sadly.

My normal way to troubleshoot is simple to do a “tracert http://www.google.dk&#8221; and to notice what network adapter is being used for the communication.

Sometimes it picks the wrong nic (one without Internet access) for whatever reason (you did remember to set the metric above, right? This is what it does). “Ipconfig /flushdns” sometime solves the problem otherwise disable the offending nic in the guest (temporarily).

VMWare or Hyper-V for Virtualization?


On every project I work we use virtualized development machines. It is almost a requirement for SharePoint development and I would recommend it to all over physical servers, simply to keep matters (projects) separate and to avoid the inevitable pollution of any dev environment.

So the question always becomes which technology should I choose? VMWare or Hyper-V?

Traditionally I’ve always opted for VMWare as it sports more features and has less operating system requirements. I’ve used VMWare Server GSX, 1 and 2 and Workstation 4 till 7 (I try to avoid the Player). VMWare basically runs on everything (but requires some CPU support to virtualize 64 bit Guest OS) while (latest) Hyper-V requires Windows Server 2008 R2.

So I finally found some time to sit down and compare the two. Now there are a lot of variables here so I’ve cut it down to me being interested in getting the most out of the Virtual Machine in terms of performance of the Guest OS. I do not test how well it works for multiple servers, how it works for databases etc.

I compare VMWare Workstation to Hyper-V, one is a program the other a server like thingy. It might be an apples and oranges comparison however it is the choice I would usually have when working in SharePoint. Price does not matter to me – my time does.

Setup

I’ve recently reinstalled my desktop computer with Windows Server 2008 R2 x64 (SP1) and configured it to be usable as a desktop operating system. I’ve basically enabled all the features to make it look and behave almost as Windows 7 and giving me the additional option of having fun with Hyper-V.

I highly recommend looking Shinvas posts (part 1 and 2) for the how to – it is by far the better option virtualization or not.

Hardware

This is a modest PC a few years old:

CPU: E8400, 1 CPU, 2 Cores, 3 GHz

Mem: 1.111 GHz DDR3, 6 GB

Disk: Three 2 x Raid 0 (bad planning in HD buys resulted in three not one raid drive)

Software

Host is running Windows Server 2008 R2 x64 sp1.

I’ve enabled the Hyper-V role and configured it appropriately. After that I found that you cannot have both Hyper-V enabled and install/run VMWare workstation as they both come with their own version of a Hypervisor, though VMWare’s runs on top of the OS and Hyper-V the other way around. That can be solved with a dual boot configuration to the same system, one with Hyper-Vs Hypervisor (phew) enabled and one without (here).

VMWare is VMWare workstation 7.1.4.

For performance testing I used SiSoftware Sandra 2011 sp2c which should be well known and reliable. I’ve used HDTunePro for disk measurements though because Sandra was very unreliable for that (I don’t believe in x10 increase in speed just because the disk is now virtual).

Virtual Machines

I’ve unpacked an old favorite VM of mine originally made with VMWare Workstation that is a full SharePoint 2010 single server development box with SharePoint, SQL, Office and Visual Studio (though no AD). It includes VMWare tools.

I removed all snapshots and converted it to a Hyper-V VHD with VMHD to VHD (ancient tool that still works perfectly) and created a new VM for Hyper-V from that. Removed remnants of VMWare and installed the integration service components that come with Hyper-V. Also ensure that no differencing disk is in play.

The two VMs are therefore picture perfect identical and I’ve seen no issues due to the conversion at all.

I’ve executed a number of tests and on both VMWare and Hyper-V you’ll receive (by far) the best performance if you match the number (and type) of virtual CPUs with the physical numbers on the host. Therefore the VMs are configured to use 2 CPUs (Hyper-V: 2 CPUs, VMWare: 1 CPU two cores).

Results

We need some graphs! In a minute… J

To understand the following you need to understand that enabling Hyper-V installs the Hypervisor which will then slow down the host machine even when Hyper-V is not used. Your host will act as a kind of pseudo virtual machine.

Therefore I compare the following configurations:

  1. Base: Host with no hypervisor (i.e. Hyper-V disabled)
  2. Host with with hypervisor/Hyper-V
  3. Hyper-V Virtual Machine
  4. WMWare Virtual Machine, normal priority
  5. VMWare Virtual Machine, high priority

What is interesting is the performance numbers compared to the bare host and the goal is to get as close to 100% as possible.

What is measured? I’ve taken a cue from a benchmarking post at Capitalhead (excellent post!) and I’ve measured

  • “Processor Cryptography”, basically core CPU performance
  • “Processor Arithmetic” CPU performance for floating point calculations
  • “Memory Bandwidth”
  • “Disk” / “File System Performance” – to keep it simple just the average amount of data transferable is measured. Note: This measurement has been very hard to get a reliable figure for, so I’ve used both Sandra and HD Tune Pro.

Every measurement was repeated 3-5 times and averaged (took quite a while L).

The following graph is the sum of it all measured relatively to the base performance numbers, i.e. I do not consider the absolute numbers to be all that interesting:

There does not seem to be too much penalty on the host to have Hyper-V/hypervisor enabled only 6% in arithmetic. It’s somewhat better than Capitalhead, cause could be SP1, different hardware and measurement technique.

The Hyper-V VM performs consistently well in all categories, where VMWare lags a bit in the memory and arithmetic categories. Interesting the Hyper-V VM performs better than the host in arithmetic which is likely due to measurement inaccuracy.

VMWare priority seems to be of minor importance.

Conclusion

So the big question is what to choose.

From the performance test it is clear that the difference is really not that big. That means that no matter your choice it’ll work 😉 It also makes it a bit harder to choose.

Note that there are many variables and different hardware will likely have slightly different characteristics however I do believe the data is valid and representative.

Feature wise VMWare wins:

  • VMWare Workstation generally sports a lot more features than Hyper-V, the one I consider most important is the Snapshot trees that does nearly as developed in Hyper-V. Better networking support, shared folders, console drag and drop, ACE, unity, etc.
  • Hyper-V wins (in my mind) a bit on administration though I know that is because we’re comparing a server product with a workstation here, though the same conclusion is valid for the VMWare server as well (it definitely does not apply to any of their datacenter products). I’m a bit annoyed with the network support as it apparently does not support wireless network adaptors (ridiculous limitation that you need to use Internet Connection Sharing to get around). Once networking is running and you access the server through Remote Desktop the other stuff with drag and drop and shared folders does not matter.

Performance wise Hyper-V wins:

  • It is very impressive to only loose about 4% in performance (excluding the disk measurement) relative to the bare metal host – at the expense of the host
  • VMWare is naturally disadvantaged here as they do not have the option of penalizing the host and have to work on top of it. It simply is slower and the only way to remedy that is to install the full ESX server, which should have at least similar performance characteristics as the Hyper-V (at least of you only install Server 2008 Core)

For me I’ll choose Hyper-V from now on.

I like the performance and I can get around the feature limitations and I don’t care about Unity etc. That said I’ll likely continue to have a dual boot setup, just in case.