Reputation: 5002
Earlier I was reading a great answer on SO and I wondered why it has not been emulated yet in PowerShell.
In unix/linux, we can use the time
command as a simple benchmark tool.
$ time ./script1.sh
real 0m1.005s
user 0m0.000s
sys 0m0.008s
In powershell, we can use the measure-command
similarly:
$ Measure-Command {java post_incr}
Days : 0
Hours : 0
Minutes : 0
Seconds : 1
Milliseconds : 18
Ticks : 10188003
TotalDays : 1.17916701388889E-05
TotalHours : 0.000283000083333333
TotalMinutes : 0.016980005
TotalSeconds : 1.0188003
TotalMilliseconds : 1018.8003
But this is not the same as the time
, which reports the real, user and sys (See the difference between the three in the linked SO Answer.)
This (time
) is obviously such a useful little tool. Are there any user written cmdlets for this functionality or is it already in V3 or planned for future releases?
Upvotes: 16
Views: 5418
Reputation: 57
Warning, PowerShell ahead.
Some coffee helped me come up with this:
function time { $Command = "$args"; Measure-Command { Invoke-Expression $Command 2>&1 | out-default} }
And if you want it to output nothing, just replace with out-null:
function timequiet { $Command = "$args"; Measure-Command { Invoke-Expression $Command 2>&1 | out-null} }
You use it like this:
PS C:\> time sleep 5
Days : 0
Hours : 0
Minutes : 0
Seconds : 4
Milliseconds : 990
Ticks : 49906722
TotalDays : 5,77624097222222E-05
TotalHours : 0,00138629783333333
TotalMinutes : 0,08317787
TotalSeconds : 4,9906722
TotalMilliseconds : 4990,6722
PS C:\>
Upvotes: 4
Reputation: 15707
The process you are trying to measure may also be forking and running in the background which causes the Measure-Command measurement to be cut short. You can use Start-Process with the -Wait parameter to get the full time measurement that you expect. Here is an example that shows that it takes stackoverflow.com 34 seconds to close an idle connection:
$program = 'telnet'
$ArgumentList = 'stackoverflow.com 80'
$WorkingDirectory = 'c:\'
Measure-Command {
$p = Start-Process -FilePath $program -ArgumentList $ArgumentList -Wait -PassThru -WorkingDirectory $WorkingDirectory -NoNewWindow;
Write-Host $p.ExitCode;
}
#Output:
0
Days : 0
Hours : 0
Minutes : 0
Seconds : 34
Milliseconds : 37
Ticks : 340370635
TotalDays : 0.000393947494212963
TotalHours : 0.00945473986111111
TotalMinutes : 0.567284391666667
TotalSeconds : 34.0370635
TotalMilliseconds : 34037.0635
Upvotes: 1
Reputation: 301157
I used both the times provided by System.Diagnostics.Process
and GetProcessTimes
to come up with an implementation for time
:
$source=@'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public class Timer
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GetProcessTimes(IntPtr handle, out long creation, out long exit, out long kernel,
out long user);
public static void Time(string file,string args)
{
long user,kernel,exit,creation;
Process proc = null;
proc = Process.Start(file,args);
proc.WaitForExit();
GetProcessTimes(proc.Handle, out creation, out exit, out kernel, out user);
long real = exit - creation;
Console.WriteLine("real {0}\nuser {1}\nsys {2}", real / 10000000.0, user/10000000.0,kernel/10000000.0);
}
}
'@
Add-Type -TypeDefinition $source -Language CSharpVersion3
function time ($scriptblock) {
$file = "powershell";
$args = $scriptblock;
$startInfo = new-object Diagnostics.ProcessStartInfo;
$startInfo.FileName = $file;
$startInfo.Arguments = $args;
$startInfo.CreateNoWindow = $true;
$startInfo.UseShellExecute = $false;
$startInfo.RedirectStandardOutput = $true;
$process = [Diagnostics.Process]::Start($startInfo);
$process.WaitForExit();
write-host $process.StandardOutput.ReadToEnd();
write-host real: ($process.ExitTime - $process.StartTime)
write-host user: $process.UserProcessorTime;
write-host sys: $process.PrivilegedProcessorTime;
write-host using GetProcessTimes
[Timer]::Time($file,$args)
}
time {sleep 10}
It isn't really perfect as the real time comes out as about 11 seconds ( for sleep 10
) since I am creating a powershell process and running the command in that. I will see if I can implement a cmdlet or something for this.
Upvotes: 2
Reputation: 7590
Write a C program using the GetProcessTimes function, you could find its documentation in: http://msdn.microsoft.com/en-us/library/ms683223%28VS.85%29.aspx.
In the examples of the book "Windows System Programming" comes a program that use that function to retrieve exactly what you need(Elapsed, Kernel, User times). The program is call "timep.exe" and it can be found in the runX subdirectories (the X comes from the version of Visual Studio used in the compilation) inside the zipped examples archive. Here is the author page from where you could download that archive http://www.jmhartsoftware.com/, of course the source code is also there so you could see exactly how timep.exe works.
Upvotes: 2