HOWTO: Modify empty VDI for optimal alignment of Windows

This is for discussing general topics about how to use VirtualBox.
Post Reply
Donut
Posts: 10
Joined: 23. Nov 2008, 06:27

HOWTO: Modify empty VDI for optimal alignment of Windows

Post by Donut »

Hi,

Normally, the cluster size of the host partition on which VirtualBox VDI files are stored is 4KB. (That applies to NTFS and usually ext2/3/4 host partitions.)

If the position of the start of the guest partition in the VDI file is not aligned to a 4KB boundary, when the guest reads or writes a cluster (4KB) from its partition, that will require two clusters on the host partition to be read/written, since the guest cluster data spans two host clusters. The performance impact of that will vary. It will most likely be greatest in a 4KB random read/write benchmark.

When installing Windows XP, by default the partition created by the Windows installer starts at sector 63. When installing Vista however, the partition begins at the 1MB point (sector 2048).

VirtualBox does not currently allow you to specify the alignment when creating new VDI files. This post describes how to adjust a newly-created VDI so the data corresponding to the start of the guest partition starts at a 4KB boundary in the VDI file.

[For more advanced users, it's also possible to align the "used block map" part of the VDI to fall on a cluster boundary. But that will have a much lower (possibly even not noticeable) impact on performance and I won't mention it here. It's also possible to modify a VDI in which a guest OS has already been installed.]

Note that some figures here are specific to the current VirtualBox version; future versions may differ, but the adjusted VDI will still work with future versions of VirtualBox. The description below is for a dynamically-expanding VDI. ($ before a number indicates hexadecimal.)

This procedure might look a bit tricky. Unfortunately though, if you need to create several VDIs you can't simply do this once then use "VBoxManage clonehd" to clone the empty VDI, since that removes the extra padding from the cloned VDI. Maybe someone can write a little perl script to automate this?

If the exact size of the VDI file doesn't matter, you can simply create one sized so the guest partition starts at the correct alignment (like the first example below, which is aligned optimally for XP). Generally, any multiple of 4096 MB will give a correctly-aligned XP partition. Any (multiple of 4096)+3584 will give an aligned Vista partition.

First let's create a 20GB dynamically-expanding VDI file:

Code: Select all

$ VBoxManage createhd --filename 20GB_test.vdi --size 20480
VirtualBox Command Line Management Interface Version 3.0.12
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Disk image created. UUID: 64097a22-e0df-44b3-91bf-7a0692d36990
The VDI file is created in ~/.VirtualBox/HardDisks/. It is 82432 = $14200 bytes long, so the disk data will begin at offset $14200 in the file. (That number is stored in the VDI header at offset $158.)

Generally, the total size of data in the VDI file before the disk data begins is (with the current version of VirtualBox):
512 + 4*(size in MB), rounded up to a multiple of 512.

In this case, because I chose a round number for the size, it turns out that the XP partition will start at a multiple of 4KB, so everything is okay. 63*512 = 32256 = $7E00. $7E00 + $14200 = $1C000.

But what if we install Vista instead? The partition created by the Vista installer will begin at sector 2048 (i.e. at position $100000). Adding $14200 to that makes $114200, which is not a multiple of 4KB. We need to add $E00 = 3584 bytes to the VDI file and modify the VDI header to align the Vista partition.

To add that number of bytes you can do this (from Linux/Unix command line):

Code: Select all

$ cd ~/.VirtualBox/HardDisks
$ dd if=/dev/zero bs=3584 count=1 | cat >>20GB_test.vdi
Next we need to change the offset in the VDI header from $14200 (00 42 01 00) to $15000 (00 50 01 00). There are a couple of ways to do that. The manual way is to use a hex editor. Move to offset $159 and change 42 to 50. Or you can use this command:

Code: Select all

$ echo P | dd bs=1 count=1 of=20GB_test.vdi conv=notrunc seek=345
The VDI is now optimally aligned for installation of Vista.


One more example...

Code: Select all

$ VBoxManage createhd --filename 123456_test.vdi --size 123456
VirtualBox Command Line Management Interface Version 3.0.12
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Disk image created. UUID: b23f0c35-4b50-440a-a02c-9a0e7a4e48b1
That VDI is 494592 = $78C00 bytes long; 512 + 4*123456 = 494336, which rounds up to 494592.

Align for XP
For XP, sector 63 would start at offset $78C00 + $7E00 = $80A00. To align that on a 4KB boundary, we need to add $600 = 1536 bytes so it starts at offset $81000. So similarly to before:

Code: Select all

  $ cd ~/.VirtualBox/HardDisks
$ dd if=/dev/zero bs=1536 count=1 | cat >>123456_test.vdi
The field at offset $158 in the VDI needs to be changed from 00 8C 07 00 to 00 92 07 00. So use hexedit to make that change and save it. Now the VDI is optimally aligned for XP.

Align for Vista
Sector 0 starts at offset $78C00. So we need to add $400 = 1024 bytes for the Vista partition to be aligned:

Code: Select all

  $ cd ~/.VirtualBox/HardDisks
$ dd if=/dev/zero bs=1024 count=1 | cat >>123456_test.vdi
And change the field at offset $158 in the VDI from 00 8C 07 00 to 00 90 07 00. So use hexedit to make that change and save it. Now the VDI is optimally aligned for Vista.

If someone wants to take the time to run some benchmarks, I'd be interested to know how much difference there is between aligned and non-aligned VDIs. Attached is an archive containing a normal 123456MB VDI, and XP- and Vista-aligned VDIs of the same size.
Attachments
Aligned_test_VDIs.tar.gz
Normal, XP-, and Vista-aligned 123456MB empty VDI files
(2.13 KiB) Downloaded 78 times
mpack
Site Moderator
Posts: 39156
Joined: 4. Sep 2008, 17:09
Primary OS: MS Windows 10
VBox Version: PUEL
Guest OSses: Mostly XP

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by mpack »

I hesitate to blow my own trumpet, but... For those interested in the idea, my CloneVDI tool already attempts to do this. Meaning that every VDI it creates has a cluster alignment which is intended to be usually optimal. This is one reason why a cloned VDI is sometimes slightly larger than the input VDI - it's because of the padding I insert to align the boot partition.

In fact my tool adjusts the image offset in the output VDI file so that LBA 63 (which is where the first partition starts on nearly all of my VDIs), is aligned on a 4K VDI file boundary - hence, as you mention, clusters inside the guest OS will have a one to one mapping with clusters on the host fileystem, which should result in improved performance.

I was not aware that Vista starts from LBA 2048, never having been a Vista user. I have come across a Win7 guest which started at LBA 128. I've had an item on my "to-do list" for a long time to stop assuming LBA 63, and instead get the partition start LBA from the source disk MBR. I had forgotten about that to-do item until I read your message.
Donut
Posts: 10
Joined: 23. Nov 2008, 06:27

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by Donut »

Feel free to blow your own trumpet, it sounds like CloneVDI could be very useful!

If I might make a couple of suggestions: by default I suggest you pad the VDI so the "block map" (which is at offset 0x200 in VDI files created by VirtualBox) starts at offset 0x1000 (i.e. 4KB into the file). And pad the block data to also start on a 4KB boundary.

For already-partitioned VDIs, as you say you could check the MBR and default to aligning sector 63 if the first partition starts there. But best to allow the user to override that if they want (user might want to reformat and install another OS on that VDI). Allow the user to specify alignment for the "block map", and alignment and offset for the block data.

So someone looking to install XP would use alignment 0x1000, offset 0x200. Someone looking to install Vista or Windows 7 would use alignment 0x1000, offset 0.

The host partition might have an NTFS cluster size of 8K or more, that's why it's a good idea to allow the user to specify alignment rather than always use 4K.
mpack
Site Moderator
Posts: 39156
Joined: 4. Sep 2008, 17:09
Primary OS: MS Windows 10
VBox Version: PUEL
Guest OSses: Mostly XP

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by mpack »

Donut wrote:If I might make a couple of suggestions: by default I suggest you pad the VDI so the "block map" (which is at offset 0x200 in VDI files created by VirtualBox) starts at offset 0x1000 (i.e. 4KB into the file). And pad the block data to also start on a 4KB boundary.
I suspect that the block map is read once and thereafter buffered in (discardable) memory - at least that's what I'd do. So, I expect there would be no measurable benefit to aligning the block map on a 4K boundary. Aligning the drive image on a 4K boundary would be self defeating - it would mean that the boot partition cannot be aligned optimally - and it's the boot partition that is important, not the MBR and and track0 - which is only typically accessed once per boot.
Donut wrote:For already-partitioned VDIs, as you say you could check the MBR and default to aligning sector 63 if the first partition starts there. But best to allow the user to override that if they want
No, I don't believe in padding out the UI with obscure options. Better to take automatic steps which benefit the majority of users most of the time.
Donut wrote:The host partition might have an NTFS cluster size of 8K or more, that's why it's a good idea to allow the user to specify alignment rather than always use 4K.
I have not encountered an NTFS partition that used anything other than 4K clusters btw. I don't see why anyone would do that: a quick calculation tells me that 4K clusters even using 32bit cluster numbers will allow single drives with capacities up to 16TB.
Donut
Posts: 10
Joined: 23. Nov 2008, 06:27

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by Donut »

First, an update to my original post. I mentioned that you can't use VBoxManage clonehd to clone an aligned VDI file, because that removes any extra padding from the cloned VDI. (In addition, VBoxManage clonehd takes ages to clone an empty VDI.)

If you want to construct one aligned VDI and easily create many clones (e.g. for installing other OSes in), you can instead do this:
- Copy the aligned VDI file from the command prompt or Explorer etc. if using Windows.
- To change the UUID of the copy, use this command: VBoxManage internalcommands sethduuid filename.vdi

I don't know how often VirtualBox writes the block map to disk, but whenever a new (1MB) block is written for the first time, the block map needs to be updated. How often the change is committed to disk probably depends on the host OS configuration. Even if there is only a very small performance benefit, an extra 3.5KB to align the block map would be worth it IMO.

For an already-partitioned VDI, of course the best option will be to detect the location of the first partition and default to aligning that. However, when the VDI is empty or has no partition table, the optimal alignment depends on which OS the user plans to install, so I do think you need to ask the user in that case.

There are cases where the user might want to align on a 4KB boundary even when installing XP, Linux or whatever. For example, if they have an SSD and will be moving the VDI data to the bare SSD in future, they would partition the VDI carefully before installing the guest OS, so the partition begins on a 4KB boundary. Then the optimal alignment of the VDI on the host drive would be 4KB too.

Regarding cluster size, remember FAT32 and the new ExFAT use much larger sizes, and it is possible to specify the size when formatting an NTFS partition. (Apparently, when converting a FAT partition to NTFS, at least Windows 2000 uses a 512-byte cluster size. That's kind of moot though; in that case the default VDI layout is aligned enough. :D )
mpack
Site Moderator
Posts: 39156
Joined: 4. Sep 2008, 17:09
Primary OS: MS Windows 10
VBox Version: PUEL
Guest OSses: Mostly XP

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by mpack »

Donut wrote:For an already-partitioned VDI, of course the best option will be to detect the location of the first partition and default to aligning that. However, when the VDI is empty or has no partition table, the optimal alignment depends on which OS the user plans to install, so I do think you need to ask the user in that case
Sorry, you mentioned that idea before, and I forgot to comment on it.

IMHO that still doesn't need an option: the best strategy is to install your OS and then re-CloneVDI it with the compact option enabled. In addition to aligning the boot partition it will clean out all the extra used blocks (now unused) created during the install, plus defragment the block order. All of these steps together result in minimum space and best possible performance.

Of course as I previously mentioned, the current version of CloneVDI presently assumes that the partition will start at LBA 63 - so this "best strategy" should be understood as probably applicable to the current CloneVDI version (v1.42), or definitely applicable to the next version.

I still don't agree that it's worthwhile to align the block map. Even assuming that the dynamic VDI is growing continuously (which obviously can't be true for very long), it's still only one update to the block map per 1MB of user data written. So, for every 256 new clusters written, the block map gets written once (and clever code would mean that you don't need to write the entire block map, just writing the affected sector would do). Bear in mind that you have a block map update penalty regardless, the only saving we are discussing comes from the difference between the block map being unaligned vs aligned. Lets say that an unaligned cluster write takes twice as long: that means we are talking about an overhead of 1 in 257 (0.4%) vs 2 in 258 (0.8%) - a speed gain of 0.4%, and I repeat, only while the VDI is growing, and I'm also assuming that the block map is updated immediately (no lazy writes). To me that means this idea just isn't worth thinking about.
Leolo
Posts: 25
Joined: 8. Aug 2010, 19:43
Primary OS: MS Windows 2008
VBox Version: PUEL
Guest OSses: Windows 7

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by Leolo »

Can someone confirm if this problem has been solved in newer versions of VirtualBox?

I've just created a new 20 GiB Dynamic VDI file and I've noticed that the guest data now starts at offset 0x015000
but Donut's post implies that it used to start at offset 0x014200 in the past.

Does this mean that VirtualBox creates dynamic VDI files optimized for Vista guests by default?

There's no need to tweak anything anymore??
mpack
Site Moderator
Posts: 39156
Joined: 4. Sep 2008, 17:09
Primary OS: MS Windows 10
VBox Version: PUEL
Guest OSses: Mostly XP

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by mpack »

Leolo wrote:I've just created a new 20 GiB Dynamic VDI file and I've noticed that the guest data now starts at offset 0x015000
but Donut's post implies that it used to start at offset 0x014200 in the past.
I assume you already know, but: guest data comes after the block map, and the block map size depends on the number of blocks, i.e. with disk size. 0x14200 was where Donut's disk happened to start, but that was not a constant.

As to whether VirtualBox now aligns the image data for performance, well it does seem to be a suspiciously round number, doesn't it. Lets see... it used to be the case that the header took up 472 bytes and the image data would start nBlocks*4 bytes after that. If 20GB means 20*1024^3 then that means an offset of 472+20480x4 = 82392 = 0x141D8. So, it looks like the image start has indeed been rounded up to the next 4K boundary. Unfortunately that only helps the guest performance if the guest also aligns partitions on a 4K boundary (Vista may indeed do so).

Edit: actually that's not correct. VBox requires the block table and image to begin on 512 byte boundaries , so the actual offset should be SECT_PAD(472)+SECT_PAD(20480x4) = 82432 = 0x14200, which matches what Donut found in the past. Looks like things have definitely changed, and I do vaguely recall a mention of this in the changelog somewhere, not sure which version.
Leolo
Posts: 25
Joined: 8. Aug 2010, 19:43
Primary OS: MS Windows 2008
VBox Version: PUEL
Guest OSses: Windows 7

Re: HOWTO: Modify empty VDI for optimal alignment of Windows

Post by Leolo »

I didn't know that the block map size was variable at first. I discovered this fact later when I created a new dynamic 500 GiB VDI and noticed that the starting size was different!

However, it's interesting to note that the difference between 0x015000 and 0x014200 is a very suspicious number: 0x0E00 (or 3584 in decimal). It's exactly the same number recommended by Donut for Vista guests!!

To me this looks like VirtualBox developers have decided to optimize by default for newer operating systems. And now the people who are using an older guest OS will be the ones who'll have to do the tweaking.

It seems reasonable to me, although I would much prefer to have a tool that would let you choose the alignment yourself.
Post Reply