Monitor Citrix PVS ‘Cache In Ram’ Size Using Powershell

I’m a firm advocate of Provisioning Services ‘Cache in RAM with overflow on hard disk’ leveraging operating system RAM for write-cache. This results in better response times and a greater number of IOPS for the write-Cache than using traditional SAN or Local storage.

However, careful planning and monitoring of the size of this cache is imperative as a breach in the available RAM will cause an overflow to the assigned slower disk which dramatically reduces performance.

Much speculation has surrounded how to monitor the write-cache with some relying on the Target Device System Tray data but this only reflects the amount of physical cache used.

I wanted to be able to monitor the amount of Ram Used so that a typical usage baseline at a customer of mine could be taken.

Buried away in the Citrix eDocs (as most things are!) is reference to the actual metric that gives an indication of how much cache in Ram is in use. This can be done by checking the Pool Nonpaged Memory and is shown in the task manager.


In this case the Write-Cache is around 913MB minus some other elements, normally in my experience equate to under 100Mb.

To test this I copied 1Gb of files to the C Drive on the target device and the Nonpaged memory increased by 1Gb. What was interesting was that by removing the 1GB’s of data released the Nonpaged Memory, I wasn’t expecting that.

Using the task manager to check usage is not very practical, so I used WMI to provide the value and obtained this by writing a PowerShell function :-

Using this code we can get the values of multiple servers by using the pipeline eg:


Hope you find it useful and any improvements please add comments below.


Matthew Nichols


  • Pingback: PvS – Create Devices | Carl Stalhood

    • Hi Matt,

      Just wanted to say thanks for the script. I made a few modifications to your script that allow additional items to be captured. I added some error handling, properties, and leveraged PowerShell’s native formatting. I’m also planning future updates such as Cache Size and usage.

      LazyITAdmins Consulting and Contracting

      Function Get-PVSRamCache
      [Parameter(Position = 0, Mandatory = $false, ValueFromPipeline = $true)]
      [String]$ComputerName = $Env:ComputerName,

      [Parameter(Position = 1, Mandatory = $false)]
      [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty
      Foreach ($Computer in $ComputerName)
      Write-Verbose -Message “Calculating Nonpaged for $Computer”
      $TotalNP = [math]::truncate((Get-WmiObject Win32_PerfFormattedData_PerfOS_Memory -ComputerName $Computer -Credential $Credential -ErrorAction Stop).PoolNonPagedBytes /1MB)
      Write-Verbose -Message “Complie successful results for $Computer”
      $psobject = @{ComputerName = $Computer; NonpagedMB = $TotalNP}
      Write-Warning -Message “Can’t Connect to $Computer. $_”
      Write-Verbose -Message “Complie failure results for $Computer”
      $psobject = @{ComputerName = $Computer; NonpagedMB = $null}
      $Output = New-Object -TypeName psobject -Property $psobject
      Write-Output $Output
      } # End Foreach loop Script Block
      } # End Process Script Block
      } # End Function Get-PVSRamCache

  • Useful stuff, it’s super important to get this sizing right if you are using it as there is a misapprehension that when you overflow to disk, you get the performance of the underlying disk, you don’t. A rule of thumb for this is divide disk I/O perf by 3 and multiply latency by 4 for the actual perf you will get. In order to ensure a consistent user experience when using PVS RAM + Overflow you must ensure you supply enough RAM to each VM to contain the working set of data in normal operation.

  • Nick Rintalan

    Great stuff – I’ve mentioned in passing a couple times (webinars, blogs, etc.) that this feature uses NPP memory vs the old PVS cache lists and it also supports TRIM functionality…but this example you’ve provided makes it crystal clear and the PoSh cmdlet will definitely come in handy. Nice work.


    Lead Architect, CCS

  • Great Small Simple script.

  • Great stuff.
    I like the ControlUp integration.

  • Useful code! Great! If you don’t mind I include this in my PVS Health Check Script ( – ok for you?

  • Einrich VonDummy

    Not sure I’m doing this correctly, but when I log onto one of the XA 7.6 servers… I open an admin powershell, set the execution policy to allow running scripts, then call the script and nothing happens.

    ps> .\getramcache.ps1 Get-PVSRamCache [enter]

    I’ve tried calling out the server name, though I’m logged into the box I want to monitor.

    • Change the extension from .ps1 to .psm1 and run ‘Import-Module .psm1. Now you should be able to run Get-PVSRamCache.

      • The formatting ate the command. You have to run Import-Module FILENAME.psm1 (in your case, it should be ‘Import-Module getramcache.psm1’.

        • Einrich VonDummy

          Awesome, thanks so much!! I was always curious if it really matched up closely with the non-paged pool ram listed in the task manager … which it does 🙂

  • Sugiono Setiawan

    Sorry to bring this up but does the script support cache to device RAM only? I tried using the script as part of ControlUp and it comes up with “Disk cache type not supported in this script”.

    • @Sugiono – Hi mate the script was developed as trying to determine the cache size when it is in Ram is difficult. Other WriteCache locations create files which are are easy to determine the size of.

      • I thought so too so no worries. I’ll definitely keep this in mind for other PVS deployment that we look after. Thanks

  • Peter Stoughton

    Management wants me to run this against a little over 1000 desktops set cache on ram. been trying to read out a file and pipeline as well as use a foreach loop. How would you handle this, thanks Pete.

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.