Diagnosing IIS Slow Time-Taken: Network Bottleneck vs. Server-Side Performance Issues


2 views

When analyzing IIS logs showing unexpectedly high time-taken values while server-side metrics (ASP.NET processing time, CPU, disk) remain normal, we're typically dealing with one of these scenarios:

  • Network latency between client and server
  • Bandwidth saturation on either endpoint
  • TCP window scaling issues
  • Client-side throttling (intentional or accidental)

Since you only have server access, here's how to gather conclusive evidence:

# PowerShell: Check active connections during the incident
Get-NetTCPConnection -State Established | 
Where-Object {$_.RemotePort -eq 80 -or $_.RemotePort -eq 443} |
Select-Object CreationTime,OwningProcess,RemoteAddress,RemotePort |
Sort-Object CreationTime -Descending

# Check for retransmissions (requires admin)
netsh interface tcp show global

Enhance your IIS logging to capture network-related metrics:

<system.webServer>
    <tracing>
        <traceFailedRequests>
            <add path="*">
                <traceAreas>
                    <add provider="ASP" areas="Infrastructure,Module,Page" verbosity="Verbose" />
                    <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,
                    Cache,RequestNotifications,Module,FastCGI,WebSocket" verbosity="Verbose" />
                </traceAreas>
                <failureDefinitions statusCodes="200-999" />
            </add>
        </traceFailedRequests>
    </tracing>
</system.webServer>

Provide these troubleshooting steps to your client:

  1. Run continuous ping tests during the incident:
    ping -t your.server.com
  2. Capture TCP dumps during slow requests:
    netsh trace start capture=yes tracefile=client_trace.etl
  3. Check network bandwidth utilization using Resource Monitor

For XML-based web services, add these diagnostic headers to your responses:

// C# example
HttpContext.Current.Response.Headers.Add("X-Server-ProcessingTime", 
    stopwatch.ElapsedMilliseconds.ToString());
HttpContext.Current.Response.Headers.Add("X-Response-Size", 
    Encoding.UTF8.GetByteCount(xmlResponse).ToString());

To verify your hypothesis, simulate network conditions with Fiddler or Clumsy:

// FiddlerScript to simulate 1Mbps connection
if (oSession.HostnameIs("your.server.com")) {
    oSession["request-trickle-delay"] = "500"; 
    oSession["response-trickle-delay"] = "500";
}

When troubleshooting IIS performance issues, the discrepancy between server-reported processing time (ASP.NET logs showing 100ms) and client-perceived latency (20 seconds in IIS logs) typically points to network-level bottlenecks. The time-taken field in IIS logs represents the entire HTTP transaction lifecycle, including:

Client Request → Network Transit → Server Processing → Network Transit → Client Receipt

These metrics help isolate network issues:

  • sc-bytes vs cs-bytes: Large response sizes magnify network latency
  • sc-substatus 0 with high time-taken suggests successful-but-slow transfers
  • Compare time-taken with ASP.NET's BeginRequest/EndRequest timestamps

Without client access, implement these diagnostic measures:

// PowerShell script to correlate IIS logs with performance counters
Import-Module WebAdministration
$logEntries = Get-Content "C:\inetpub\logs\LogFiles\W3SVC1\u_ex210101.log" | 
    ConvertFrom-Csv -Delimiter ' ' -Header ($header -replace '#Fields: ','').Split(' ')

$logEntries | Where-Object { $_.time-taken -gt 5000 } | ForEach-Object {
    $timestamp = [datetime]::ParseExact($_.date+" "+$_.time, "yyyy-MM-dd HH:mm:ss", $null)
    Get-Counter "\Process(w3wp)\% Processor Time" -SampleInterval 1 -MaxSamples 30 |
        Where-Object { $_.Timestamp -ge $timestamp.AddSeconds(-5) -and 
                      $_.Timestamp -le $timestamp.AddSeconds(5) }
}

Provide clients with this troubleshooting protocol:

  1. Run continuous traceroutes during the issue:
    @echo off
    :loop
    tracert your.server.com >> network_log.txt
    timeout /t 30
    goto loop
    
  2. Capture simultaneous Wireshark traces with this filter:
    tcp.port == 80 || tcp.port == 443 && ip.addr == your.server.ip
  3. Compare with Fiddler trace timings for HTTP layer verification

For SOAP services particularly affected:

// Web.config compression settings for XML responses
<system.webServer>
  <httpCompression>
    <dynamicTypes>
      <add mimeType="text/xml" enabled="true" />
      <add mimeType="application/soap+xml" enabled="true" />
    </dynamicTypes>
  </httpCompression>
  <urlCompression doStaticCompression="true" doDynamicCompression="true"/>
</system.webServer>

Enable these IIS features for deeper analysis:

# Enable Advanced Logging for network metrics
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/sites/siteDefaults/logFile" -name "logExtFileFlags" -value "Date,Time,ClientIP,ServerIP,Method,UriStem,UriQuery,HttpStatus,Win32Status,TimeTaken,ServerPort,UserAgent,Cookie,Referer,ProtocolVersion,Host,HttpSubStatus"

This captures TCP-level metrics that help differentiate between:

  • TCP retransmissions (packet loss)
  • Slow-start throttling
  • Bandwidth congestion