Measuring GPU Utilization in Remote Desktop Services

I recently spent some time experimenting with GPU Discrete Device Assignment in Azure using the NV* series of VM.  As we noticed that Internet Explorer was consuming quite a bit CPU resources on our Remote Desktop Services session hosts, I wondered how much of an impact on the CPU using a GPU would do by accelerating graphics through the specialized hardware.  We did experiments with Windows Server 2012 R2 and Windows Server 2016. While Windows Server 2012 R2 does deliver some level of hardware acceleration for graphics, Windows Server 2016 did provide a more complete experience through better support for GPUs in an RDP session.

In order to enable hardware acceleration for RDP, you must do the following in your Azure NV* series VM:

  1. Download and install the latest driver recommended by Microsoft/NVidia from here
  2. Enable the Group Policy Setting  Administrative Templates\Windows Components\Remote Desktop Services\Remote Desktop Session Host\Remote Session Environment\Use the hardware default graphics adapter for all Remote Desktop Services sessions as shown below:

To validate the acceleration, I used a couple of tools to generate and measure the GPU load. For load generation I used the following:

  • Island demo from Nvidia which is available for download here.
    • This scenario worked fine in both Windows Server 2012 R2 and Windows Server 2016
    • Here’s what it looks like when you run this demo (don’t mind the GPU information displayed, that was from my workstation, not from the Azure NV* VM):
  • Microsoft Fish Tank page which leverages WebGL in the browser which is in turn accelerated by the GPU when possible
    • This proved to be the scenario that differentiated Windows Server 2016 from Windows Server 2012 R2. Only under Windows Server 2016 could high frame rate and low CPU utilization was achieved. When this demo runs using only the software renderer, I observed CPU utilization close to 100% on a fairly beefy NV6 VM that has 6 cores and that just by running a single instance of that test.
    • Here’s what FishGL looks like:

To measure the GPU utilization, I ended up using the following tools:

In order to do a capture with Windows Performance Recorder, make sure that GPU activity is selected under the profiles to be recorded:

Here’s a recorded trace of the GPU utilization from the Azure VM while running FishGL in Internet Explorer that’s being visualized in Windows Performance Analyzer:

As you can see in the WPA screenshot above, quite a few processes can take advantage of the GPU acceleration.

Here’s what it looks like in Process Explorer when you’re doing live monitoring. As you can see below, you can see which process is consuming GPU resources. In this particular screenshot, you can see what Internet Explorer consumes while running FishGL my workstation.

Windows Server 2016 takes great advantage of an assigned GPU to offload compute intensive rendering tasks. Hopefully this article helped you get things started!

Capturing Logged In Remote Desktop Sessions on Servers Using PowerShell

While it’s a best practice to avoid logging on servers using Remote Desktop for management tasks, some things are just easier when you do and some things are almost impossible to do otherwise. That will change significantly with Windows Server 2016 but in the mean time, we have to manage this.

I’m sure it happened to you or to your colleagues, we sometime disconnect our RDP sessions from our beloved pet servers and forget we ever logged onto those. The problem with this is that we end up wasting precious server resources in our environment for no valid reasons. So how can we be aware of those lingering RDP sessions?

In our case, I built the following script to help us assess the situation.

For the latest version: Get-RDPSession.ps1

Here’s what the script is doing at a high level:

  1. Get a list of servers from Active Directory
  2. Load the awesome PSTerminalServices.psm1 module (it hasn’t been updated in a little while though)
  3. For each server:
    1. Capture the Remote Desktop Services sessions core information:
      1. Computer Name
      2. Domain Name
      3. User Name
      4. Connection state
      5. Time of connection
      6. Time of disconnection
      7. Time when last input was received from the user
      8. Login time
      9. User idle time
    2. For each session discovered, measure the amount of memory consumed by the user
    3. Export this data to a CSV file for further analysis

You can then easily use Excel or Power BI to perform additional analysis on your opened sessions. Here’s an screenshot from our environment where I’ve protected the names of the innocents:


You now go clean your RDP sessions and THEN go bug your colleagues about their sessions! 😉

If you have any questions about this, feel free to ask via the comments!

Remote Desktop Services VDI User Experience Monitoring

With the release of GEM Automation came a new set of capabilities to monitor core network statistics that directly affects the user experience in Remote Desktop Services Virtual Desktop Infrastructure (VDI). As we have quite a few users who are either working from home or from another country (on another continent), it became obvious we needed some extra information to assess and diagnose the experience of our users.

The core of this new functionality resides in the Windows\libWindowsRDS.psm1 module. The function that performs the grunt of the work is called Get-RDSPerfmonStatistics. An easy way to monitor your RDS infrastructure is to put the name of your brokers in RDSServers.txt and then you can simply call Monitor-RDSPerformance.ps1 without any parameters assuming you have configured your environment properly in the configuration database using ConfigurationDatabase\libConfigurationDatabase.psm1. Only the credentials of the user performing the monitoring need to be added as a configuration setting. For example, you could do this by calling the New-ConfigurationSetting function

New-ConfigurationSetting -scope Global -name AutomationCredentialUserName -value <user name>
New-ConfigurationSetting -scope Global -name AutomationCredentialPassword -value <user password>

Doing it this way allows you to easily schedule the Monitoring-RDSPerformance.ps1 script in Task Scheduler.

Once the script has been properly configured and is running, it will collect the following metrics:

  • \RemoteFX Network(*)\Current TCP RTT
  • \RemoteFX Network(*)\Current UDP RTT
  • \RemoteFX Network(*)\Total Sent Rate
  • \RemoteFX Network(*)\Total Received Rate

The script will also collect the following user information to facilitate the reconciliation of the performance data with actual users:

  • Broker computer name
  • Collection name
  • Host server name (i.e. Hyper-V host running the VM)
  • User company
  • User title

A caveat of this script to note is that session information is only refreshed a specific interval. The refresh process lists the currently active sessions in order to setup the perfmon monitoring required (i.e. target the right VDI computer). By default this is done every 30 minutes. This means if a user connects and has a session shorter than 30 minutes, there’s a potential it won’t show up in the statistics.

Here’s and idea what the data looks like in the Excel spreadsheet:


As you can see, I can slice and dice the user statistics in multiple ways in order to get to what I’m looking for. One graph that’s particularly interesting to help you assess the situation is the one in the bottom left. It shows you how many samples were within certain RTT buckets. It gives you a nice an easy way to see if the user experience is generally good or bad. It’s also important to keep an eye on the Average TCP RTT (if you are not using UDP) and the TCP RTT Jitter. They show you the average connection latency and the amount of latency variations happening.

Right now the Excel spreadsheet is not available. Once I clean our confidential data from it, I’ll publish it to CodePlex.

If you have any questions about this, feel free to leave me a comment!