SharePoint 2013: Network Latency Test script


If you are familiar with the various planning documents on TechNet, then you know that there are some very specific intra-farm network latency requirements outlined at http://technet.microsoft.com/en-us/library/cc262485.aspx.  

The requirement of interest for the blog post is:

  • There is a highly consistent intra-farm latency of <1ms one way, 99.9% of the time over a period of ten minutes. (Intra-farm latency is commonly defined as the latency between the front-end web servers and the database servers.)

In order to ensure proper functioning of the SharePoint farm this requirement must be met.  However, how do you know if the requirement is met if you can’t test it?  Well, Alex Strachan, a clever colleague that works in MCS, wrote a PowerShell script that does exactly that.  I have made some modifications to the script to better suit my preferences but the credit for this idea all goes to Alex.  Thanks Alex for sharing.  If you’d like to see his evolving version of the script please see his blog at http://blogs.technet.com/b/alexst/.

I recommend that this script be run during validation of new deployments as well as on a regular frequency post-deployment to test and verify that there are not any network latencies that have crept into the environment that could be hindering SharePoint operations.

The script performs the following steps:

  1. Ping each of the server in the “server list” to make servers are reachable.
  2. Connect to the SQL server to verify DB connectivity.
  3. Run a 10 minute ping test against each to ensure that the environment meets the <1 ms latency requirement
  4. Generates output to show the percentage of pings that complete in 5 ms, 4 ms, 3 ms, 2 ms and 1 ms respectively

Here is sample output from the script:

Test Connectivity:
Testing Ping
  Pinging SP2013DC
  Pinging SP2013SPS
  Pinging SP2013SQL
 - Succeeded 

Testing SQL Connection
 - Succeeded 

Starting network consistency tests @ 11/11/2013 14:00:28

Id              Name            State      HasMoreData     Location             Command                  
--              ----            -----      -----------     --------             -------                  
1               SP2013DC.lat... Running    True            localhost            ...                      
3               SP2013SPS.la... Running    True            localhost            ...                      
5               SP2013SQL.la... Running    True            localhost            ...                      

Gathering statistics for 10 minutes... 

Processing Data... 

SP2013DC meets the latency requirements with 0.01% of pings >1ms

SP2013SPS DOES NOT meet the latency requirements with 25.55% of pings >1ms
  (1.68% > 5ms, 3.16% > 4ms, 5.98% > 3ms, 11.86% > 2ms, 25.55% > 1ms)

SP2013SQL DOES NOT meet the latency requirements with 28.36% of pings >1ms
  (1.76% > 5ms, 3.18% > 4ms, 5.96% > 3ms, 12.47% > 2ms, 28.36% > 1ms)

To run the script, you need to edit the following variable(s) as appropriate for your environment

$hostname – a list of SharePoint server names and/or IP addresses

$SQLName – the name of the SQL server that contains the farm config DB

<#
//*********************************************************
// THIS CODE IS PROVIDED AS IS WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
// ©2013 Microsoft Corporation. All rights reserved.
//*********************************************************
#>

# Edit these variables to match your environment
$SPServerNames = "SP2013DC", "SP2013SPS", "SP2013SQL"
$SQLServername = "SP2013SQL"

#Edit this if you want to change the durations of the ping test (in minutes)
$RunTime = 10

### test connectivity ###
Write-Host "Test Connectivity:"

Write-Host "Testing Ping"
$ping = New-Object System.Net.NetworkInformation.ping

for($i=0; $i -le $SPServernames[$i].Length-1; $i++){
    Write-Host "  Pinging $($SPServerNames[$i])"
    $status = $ping.send($SPServernames[$i]).Status
        
    if($status -ne "Success"){
        throw "Ping Failed to $($SPSServernames[$i])"
        }
    }
    
Write-Host " - Succeeded `n"

### test SQL connectivity ###
Write-Host "Testing SQL Connection"
#Connect to SQL using SQlCLient the same way that SharePoint Does
$SQLConnection = New-Object System.Data.SQLClient.SQLConnection("Data Source=$SQLServername;Integrated Security=True")
$SQLConnection.Open()
if($SQLConnection.state -ne "Open"){
    throw "SQL Connection Failed"
    }
Write-Host " - Succeeded `n"

### Intra-server latency consistency test ###
Write-Host "Starting network consistency tests @ $([DateTime]::Now)"

$ScriptBlock = {
    # accept the loop variable across the job-context barrier
    param($InHost, $RunTime) 

    $start = [DateTime]::Now
    $ping = New-Object System.Net.NetworkInformation.ping
    
    $PingResults = @()
    while([datetime]::now -le $start.AddMinutes($RunTime)){ 
        $outping = $ping.send($InHost)
        if($outping.Status -ne "Success"){
            $PingResults = $PingResults + 100
            } else{
            $PingResults = $PingResults + $outping.RoundtripTime
            }
        Start-Sleep .1
        } 
    return $PingResults
    }


#run ping jobs in parallel
foreach($i in $SPServernames){
    Start-Job $ScriptBlock -ArgumentList $i, $RunTime -Name "$i.latency_test"
}

Write-Host "`nGathering statistics for $($RunTime) minutes... `n"

#wait and clean up
While (Get-Job -State "Running") { Start-Sleep $($runTime/2) }

$output = @{}
foreach($i in $SPServernames){
    $output[$i] = Receive-Job -Name "$i.latency_test"
}
Remove-Job *

#test results
Write-Host "Processing Data... `n"

$BadPings = @{}
$PercentBadPings = @{}

foreach($i in $SPServernames){
    $BadPings[$i] = $output[$i] | ?{$_ -ge 1}
    $TotalPings = $output[$i].Length
    $PercentBadPingsOver5Ms =  ($BadPings[$i] | ?{$_ -ge 5}).length/$TotalPings * 100
    $PercentBadPingsOver4Ms =  ($BadPings[$i] | ?{$_ -ge 4}).length/$TotalPings * 100
    $PercentBadPingsOver3Ms =  ($BadPings[$i] | ?{$_ -ge 3}).length/$TotalPings * 100
    $PercentBadPingsOver2Ms =  ($BadPings[$i] | ?{$_ -ge 2}).length/$TotalPings * 100
    $PercentBadPingsOver1Ms =  ($BadPings[$i] | ?{$_ -ge 1}).length/$TotalPings * 100
      
    if($PercentBadPingsOver1Ms -ge .1)
    {
        "{0} DOES NOT meet the latency requirements with {1:N2}% of pings >1ms" -f $i, $PercentBadPingsOver1Ms  
        "  ({0:N2}% > 5ms, {1:N2}% > 4ms, {2:N2}% > 3ms, {3:N2}% > 2ms, {4:N2}% > 1ms)`n" -f $PercentBadPingsOver5Ms,$PercentBadPingsOver4Ms,$PercentBadPingsOver3Ms,$PercentBadPingsOver2Ms,$PercentBadPingsOver1Ms
    } 
        else
        {
        "{0} meets the latency requirements with {1:N2}% of pings >1ms`n" -f $i, $PercentBadPingsOver1Ms
        }
    $LatencyTestFailed = 1
    }
    
#if($LatencyTestFailed -eq 1){
#    throw "Farm Latency Test Failed"
#    } 

Powershell Source: CheckNetworkLatency.ps1

I hope you find this post useful and I look forward to reading your comments.

# # # # #

Comments (7)

  1. SP2010 says:

    Looking at the script it looks that it does not have to be SP2013 specific but also can be ran on SP2010 farms as well?

  2. EricA [MSFT] says:

    SP2010:   Yes, you are correct.  This script with work with SharePoint 2010.  In fact, this script can be used to test network latency in any environment.  However, the calculations are made based upon the public guidance for SharePoint 2013.

    Eric

  3. Mohiuddin Qadri says:

    Hi Eric,

    Great script. However, I have one question. The requirement statement is:

    intra-farm latency of <1ms ONE WAY, 99.9% of the time over a period of ten minutes.

    So, we need the latency to be <1ms one way, not two way. A normal ping test is a packet sent and then receive a ping response.

    The script is taking a record of a ping response (two way), which is incorrect.

    In any case, great work.

    Mohiuddin Qadri

  4. Ripon Kundu says:

    Thanks Eric. Nice content..

  5. Will says:

    When running the script with multiple nodes, the script kicks off an additional powershell sessions.  Those subsequent powershell sessions consume 100% of the CPU on the server running the script.  Is there any way to decrease the CPU utilization that the script is using?  

  6. EricA [MSFT] says:

    Will:   Yes.   The script will start multiple jobs (one per server in the array).  If you want to reduce the amount of CPU consumed, you can increase the amount of sleep time in the script block.

    Change Start-Sleep .1 (1/10th) to something like Start-Sleep 1

Skip to main content