Blog Post

Calculate Bitmasks In PowerShell

,

Use These CPUsHave you ever had to calculate bitmasks on the fly?  I have and still do.  In this post, I’m going to show a simple PowerShell script that can be used to generate bitmask values.  But first, let’s look at a reason that you may have to use bitmasks.

Many of today’s servers have a fair number of CPUs.  It isn’t too uncommon to have 4 CPUs and for those CPUs to have 6 or 8 or even 10 cores.  This results in a fair number of logical cores.  With this there is also the fact that many servers are also being built with some level of hardware NUMA.  Resulting in variations in distances between some resources as compared to others.  For instance, the IO hub in the server might be directly connected to CPU 0 and CPU 1 may need to send requests through CPU 0 to access it.  Without going too deep into the details, the performance of all cores may not be the same when using the same resources.

Since the performance can vary when an application runs when different resources are used, it is sometimes useful to constrain the resources available to the application.  This can be done in SQL Server with CPU and I/O affinity.  It can also be done with tools, such as SQLIO, to constrain the CPU resources used with an affinity mask.  By constraining the CPUs that SQLIO can use, you’ll get more consistent results when benchmarking IO performance.

Creating the Bitmask Value

Creating a bitmask value is fairly easy.  The first value is 1, the second is 2, then 4, 8, 16, and so forth.  Each value incremental up is is double the preceding value.  This is because bitmasks are based on bits within a binary value.  The first value represents 1 then 2 and so on, same as in the pattern previously described.  If the first and second bit are enabled, the binary value would be 11 which would be 3, or bits 1 and 2 enabled.  Similarly, if bits 2 and 4 are enabled, then the binary value is 1010 and the value is 10, for values 2 and 8.

The trouble with creating bitmask values is once you get more than a few bits to check, the math for determining whether bits are enabled gets a bit tricky.  Having ten bits and all enabled, binary value of 1111111111, results in a value of 1023.  If there are some of the bits disable and others enabled, calculating the value usually takes a tool to assist.

One such tool that can be used to create bitmask values is PowerShell.  There are likely tricks for creating bitmask values that are better than what I’m using, but the code provided in Listing 1 can calculate a bitmask for the values 0 to 9.  The resulting value could be used with SQLIO to constrain the throughput test to the first ten logical CPUs on the server.  The way the bit mask is calculated, is by taking each enabled position of the bitmask and apply it as the power over 2 and then adding all of the enabled values together.  As a results of the script, the bitmask for 0 to 9 is calculated to 1023, as shown in Figure 1.

#Listing 1 - Bitmask value for values 0 to 9
$CPUList = @(0..9)
$Mask = 0
$CPUList | % { $Mask += [Math]::Pow(2, $_)}
Write-Host $Mask

Results Listing 1
Figure 1. Results for bitmask value for values 0 to 9

Along with a uninterrupted number series, PowerShell can easily calculate a series with a break in the values.  For instance, if you needed to set the bitmask to bits 0 to 4 and 10 to 14, the only need is to fill the array with the appropriate values.  In the example in Listing 2, the arrays is populated with the first five values and then appended with the second set of values.  The resulting value is 31775, which is shown in Figure 2.

#Listing 2 - Bitmask value for values 0 to 4 and 10 to 14.
$CPUList = @(0..4)
$CPUList += @(10..14)
$Mask = 0
$CPUList | % { $Mask += [Math]::Pow(2, $_)}
Write-Host $Mask

Results Listing 2
Figure 2. Results for bitmask value for values 0 to 4 and 10 to 14

Converting the Bitmask

In some cases, you may need more than the decimal value ofa bitmask.  Maybe requiring the value as a hexidecimal or binary format.  This conversion is very simple, too simple almost for it’s own blog post, but enough to add on here.  To convert to either of the other formats requires the use of Convert::ToString.  This function will accept the decimal bitmask and convert it to the desired format based on the base value provided.  For instance, to convert the bitmask for values 0 to 9 to binary the value 2 is used as the base, as provided in Listing 3 with the output provided in Figure 3.

#Listing 3 - Convert to binary
$CPUList = @(0..9)
$Mask = 0
$CPUList | % { $Mask += [Math]::Pow(2, $_)}
Write-Host $Mask
Write-Host $([Convert]::ToString($Mask, 2))

Results Listing 3
Figure 3. Results for convert to binary

In a similar fashion, converting the values for 0 to 9 to hexidecimal is just as easy.  Instead of base 2, hexidecimal is base 16.  A slight change in the previous script to change the base value, provided in the script in Listing 4, results in the hexidecimal value, as show in Figure 4.

#Listing 4 - Convert to hexidecimal
$CPUList = @(0..9)
$Mask = 0
$CPUList | % { $Mask += [Math]::Pow(2, $_)}
Write-Host $Mask
Write-Host $([Convert]::ToString($Mask, 16))

Results Listing 4
Figure 4. Results for convert to hexidecimal

Summary

As many people say at the end of most PowerShell posts, PowerShell is a powerful language that lets you easily script out tasks.  In this case, it removed the irritation associated with calculating bitmasks.  While creating bitmasks isn’t really that hard, figuring out each bits value and adding them by hand is prone to errors.  PowerShell can provide that guarantee that something isn’t missed.  How do you calculate bitmasks?  Would you use this script?

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating