Friday, December 05, 2008

Get-Process Produces Negative Numbers

I saw an interesting item over on the PowerShell newsgroup today. The poster was using Get-Process on an X64 system and was seeing negative numbers in the Working Set column against the SQL Server. The answer was a simple one, as it turns out.

The Get-Process cmdlet returns [System.Diagnostics.Process] objects, but with some added members – the cmdlet in effect expands the objects for PowerShell. Specifically, the Cmdlet adds 6 Alias Properties that are aliased to other properties in the [System.Diagnoistics.Process] Class:

  • Handles = Handlecount
  • Name = ProcessName
  • NPM = NonpagedSystemMemorySize
  • PM = PagedMemorySize
  • VM = VirtualMemorySize
  • WS = WorkingSet

This makes life easier for the admin who can use the shorter Alias property names, et:

$process = “*SQL"*”
GPS $process | ft name, ws -auto

The reason the poster was seeing negative numbers is fairly simple: the WS property is aliased to WorkingSet, but WorkingSet is a 32-bit value. In the poster’s case, the working set size overflowed the 32-bit value, resulting in a negative number being displayed. The solution is fairly simple if you look at the class’s Property details: use a different property which contains a 64- bit value. The class has several 64-bit properties:

  • NonpagedSystemMemorySize64
  • PagedMemorySize64
  • VirtualMemorySize64
  • WorkingSet64

So the solution was easy – just use:

$process = “*SQL"*”
GPS $process | ft name, workingset64 –auto

The maximum size of an Int32 is 2**32, meaning the maximum size of the WS/WorkingSet property is 4GB. Thus this problem can never occur on an I386 system since on i386, processes have a maximum size of 4GB, But as x64 becomes more common, and from Server 2008 R2 becomes the norm, this problem will grow.

Interestingly, in the API documentation MIcrosoft now state that the 32-bit values are obsolete. You could argue this is a bug in PowerShell. For PowerShell V2, Microsoft really should change the WS and other AliasProperties to alias the 64-bit properties. For CTP2, this has not been done.


BorgOvermind said...

How do I apply this to get 64-bit video adapter memory ?

I currently use "wmic path win32_VideoController get AdapterRAM"

Thomas Lee said...

First, to get the adapter ram, I'd user PowerSHell:

win32_VideoController get AdapterRAM

However - the value returned is a 32-bit numer (system.int32). The value itself is contained in a WMI class and can not be changed by customers. To fix it, MSFT would need to update the class, and then update the provider (which provides the Win32_VideoController class) and update any and all drivers that use it.

Maybe they could just add a new property (AdapterRAM64) and use it side by side - MSFT can update the win32 provider to add the new field and populate it as appropriate. The driver manufacturers could provide it as an update. And maybe MSFT could make support of 64-bit values something required for the card/driver to be certified.

TL;DR - you can't.