7

I have a curl command which response time by breaking it by each action in invoking a service.

curl -w "@sample.txt" -o /dev/null someservice-call

I want to measure the response time in a similar way using PowerShell's built-in Invoke-WebRequest call. So far I am able to get total response time using Measure-Command. Can someone please help me with this?

Content of sample.txt used in curl:

time_namelookup:  %{time_namelookup}\n               
time_connect:  %{time_connect}\n            
time_appconnect:  %{time_appconnect}\n           
time_pretransfer:  %{time_pretransfer}\n              
time_redirect:  %{time_redirect}\n         
time_starttransfer:  %{time_starttransfer}\n                            
----------\n          
time_total:  %{time_total}\n
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Rock
  • 71
  • 1
  • 1
  • 4

3 Answers3

9

time in milliseconds:

$url = "google.com"
(Measure-Command -Expression { $site = Invoke-WebRequest -Uri $url -UseBasicParsing }).Milliseconds
Falco Alexander
  • 3,092
  • 2
  • 20
  • 39
  • 1
    This works but it's not terribly performant. If I use `-method head` on this I get around 40-50 milliseconds but if I do the same thing in Firefox with HEAD it's only about 10-15 milliseconds. Similar results with a local webserver, 3-5ms vs 50-60ms. – duct_tape_coder Jun 10 '20 at 23:18
  • agree, it does not make sense for short response time tests, there is a huge overhead somewhere! – Falco Alexander Jun 11 '20 at 11:25
  • 1
    with measure command you will get everything including parsing of the actual command, creating and setting up the request and response and so on. it will not just measure request-time itself. Unfortunatly i do not know an easy way to achieve this. – Chris Oct 23 '20 at 10:30
  • 3
    Apologies for necro-bumping, but this did just help me a great deal. I think the actual property you want to report on here is .TotalMilliseconds (Milliseconds is relative to the current second) – John Perrin Jan 05 '21 at 12:04
  • `-UseBasicParsing` is not needed in PS v6+ – mlhDev Oct 31 '22 at 13:46
1

This seems to do it without any noticable overhead:

$StartTime = $(get-date)
Invoke-WebRequest -Uri "google.com" -UseBasicParsing
Write-Output ("{0}" -f ($(get-date)-$StartTime))
Andy Nugent
  • 859
  • 7
  • 21
0

As the other solutions point out, there is a performance catch when using powershell only.

The most efficient solution would probably be to write some c# with the measurements built in. But when it's not properly compiled beforehand, the loading-time will increase dramatically when the C# needs to be compiled.

But there is another way.

Since you can use almost all dotnet constructs within powershell, you can just write the same request and measurement logic within powershell itself. I have written a small method which should do the trick:

function Measure-PostRequest {
    param(
        [string] $Url,
        [byte[]] $Bytes,
        [switch] $Block
    )

    $content = [Net.Http.ByteArrayContent]::new($bytes);
    $client = [Net.Http.HttpClient]::new();
    $stopwatch = [Diagnostics.Stopwatch]::new()
    $result = $null;

    if ($block) {
        # will block and thus not allow ctrl+c to kill the process
        $stopwatch.Start()
        $result = $client.PostAsync($url, $content).GetAwaiter().GetResult()
        $stopwatch.Stop()
    } else {
        $stopwatch.Start()
        $task = $client.PostAsync($url, $content)
        while (-not $task.AsyncWaitHandle.WaitOne(200)) { }
        $result = $task.GetAwaiter().GetResult()
        $stopwatch.Stop()
    }

    [PSCustomObject]@{
        Response = $result
        Milliseconds = $stopwatch.ElapsedMilliseconds
    }
}
Adam Porad
  • 14,193
  • 3
  • 31
  • 56
Chris
  • 527
  • 3
  • 15