Friendly Units

When you are dealing with big(ger) memory or storage values, it’s often not easy to present these in a human-readable format. I don’t know about you, but I find a number like 766509056 less readable, and meaningful, then 731 MB in a report.

You can introduce some nested If-Then-Else constructs in your scripts to do the conversion, but why repeat these in all your scripts ? That’s why I decided to write me a handy function, that would solve this problem once and for all.

Update November 14th 2011: handled passing a 0 to the Log function.

With the help of some Math functions, it turns out the process is quite easy.

The function

Annotations

Line 24: In the section Big numbers and Accuracy, you will find the reason why the function uses a [double] type for the input value.

Line 29-30: The function can produce the IEC units or the more commonly used, but in fact incorrect, units. See the sectionUnit standards for the complete story.

Line 36-39: The function can only work with positive numbers and zero.

Line 41: The function uses the Log function to find out to which power of 1KB the passed value is. Since the function only needs the integer part of this number to index into the unit names array, the Floor function is applied to the number.

Line 44: The Log function returns ‘Infinite’ when you feed it 0 (zero). This If-Then-Else avoids that nuissance.

Line 47: The converted, more human-readable, number

Line 48: The unit name. If the value is greater than or equal to 1KB to the power 9, the function switches to a 1KB exponential notation. See the Unit standards section below.

Samples

Some simple examples should make it clear how the function can be used.

You can of course format the result to your own liking. This is an example on how to use the Format operator on the result.

In this example we use the CapacityMB property that is present in the object returned from the Get-Datastore cmdlet. The value is passed through the Get-FriendlyUnit function, and the result is presented in a nice format. It looks like this

Discussion points

Unit standards

There is often confusion how the units for binary multiples should be named. Is 1024 bytes a kb, a kB, a KB or KiB ? You can find a good overview, and the correct answer, on this in the Binary Prefix article on Wikipedia.

With ISO/IEC 80000 this was standardised. Those 1024 bytes should be called 1 KiB, . But in reality people are still using KB instead of the official IEC name KiB. To cope with both, the function provides a switch, called IEC, that allows you to select the ISO/IEC 80000 naming standard.

By default, the function returns the customary used symbols.

The following table shows the IEC standard defined names and the customary, but technically incorrect, names.

Value IEC prefix IEC name Customary Symbol Customary Name
1024 Ki kibi K kilo
10242 Mi mebi M mega
10243 Gi gibi G giga
10244 Ti tebi T tera
10245 Pi pebi P peta
10246 Ei exbi E exa
10247 Zi zebi Z zetta
10248 Yi yobi Y yotta

But what happens when you feed the function a number that is bigger than 1024 YB ?

In that case, the function will use a 1KB to the power expression. An example will make this clear.

This expression says, that the value is equal to 1 time 1KB to the power 9.

Big numbers and Accuracy

One question I had to answer was how to get “big” values into the function.

The following table shows what the maximum value are that you can pass with each of the ‘number’ types. I also included the ‘friendly’ names, to give you an idea where the maximum value gets you.

Maximum Value Friendly Value
int 2147483647  1.99 GB
long  9223372036854775807  8 EB
float  3.402823E+38  255.99 1KB E12
double  1.79769313486232E+308  16 1KB E102

From the table is obvious that neither [int] nor [long] would be sufficient to cover the complete range of binary multiples. The solution is fairly simple, we use a [double] for the value that goes into the Get-FriendlyUnit function.

There is one disadvantage though, with big numbers the accuracy of the result will suffer. See the following example.

While the first example still seems to produce a valid result, the second example suffers from rounding errors. The example tells us that 1 EB is equal to (1 EB – 1). So watch out when using bigger numbers!

You can expect some practical use cases of this handy function in the coming days.

12 Comments

    Tony

    @LucD
    Hi Luc

    This is a great function. Thanks for all your hard work. How would you add Provisioned space? Is it possible to get provisoned space without using the Get-View Cmdlet. I can’t seem to get your function to work properly when I run it against my datastores using the get-view cmdlet.

    Thanks

      LucD

      Thanks Tony.
      I already replied to that question in the VMTN PowerCLI community thread.
      I suspect there was a copy/paste that went wrong 🙂

    Guilhermestela

    hahahhahaa you should re-think better Carter….@LucD

    Ethan M

    Coolio. Now to integrate this into get-process. Exercise left to reader 🙂

      LucD

      @Ethan, thanks.
      You can call the function in a calculated property. Or do you have something else in mind ?

    Kyle Hanson

    Quite a useful function. I wish this was an inbuilt PowerShell cmdlet.

    Eugene

    Great. Thanks as always. Btw you are missing a “<#" at the beginning of the comment section.

      LucD

      @Eugene, thanks. And thanks for noticing the missing lines.

    jessie

    Hi,

    I really like your conversion to GB, I wonder how I can add free space to the example you gave on:

    I’m really new to powercli so Im not too sure. much thanks!!!

    Get-Datastore -Name DS1 |
    Select Name,@{N=”Capacity”;E={
    Get-FriendlyUnit -Value ($_.CapacityMB * 1MB) |
    %{“{0,7:f2} {1,2}” -f $_.Value,$_.Unit}}
    }

      LucD

      @Jessie, the Free space property is returned by the Get-Datastore cmdlet as well.
      So it’s just a matter of including it in the Select cmdlet.
      Something like this

      Get-Datastore -Name DS1 |
      Select Name,
      @{N="Capacity";E={Get-FriendlyUnit -Value ($_.CapacityMB * 1MB) | %{"{0,7:f2} {1,2}" -f $_.Value,$_.Unit}}},
      @{N="FreeSpace";E={Get-FriendlyUnit -Value ($_.FreeSpaceMB * 1MB) | %{"{0,7:f2} {1,2}" -f $_.Value,$_.Unit}}}

    Carter Shanklin

    I will punch the first person I meet who says gibibytes. Not even lying.

      LucD

      I tend to agree with you, but then …
      Chuck gibi

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.