【问题标题】:Equivalent of Unix time command in PowerShell?等效于 PowerShell 中的 Unix 时间命令?
【发布时间】:2011-12-26 18:58:06
【问题描述】:

之前我在 SO 上阅读了一篇很棒的 answer,我想知道为什么它还没有在 PowerShell 中被模拟。

在 unix/linux 中,我们可以使用time 命令作为简单的基准测试工具。

$ time ./script1.sh  

real    0m1.005s  
user    0m0.000s  
sys     0m0.008s  

在powershell中,我们可以类似地使用measure-command

$ 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  

但这与time 不同,后者报告真实、用户和系统(请参阅链接的 SO 答案中三者之间的区别。)

这(time)显然是一个非常有用的小工具。是否有任何用户为此功能编写的 cmdlet,或者是否已经在 V3 中或计划在未来的版本中发布?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    使用 GetProcessTimes 函数编写一个 C 程序,您可以在以下位置找到它的文档:http://msdn.microsoft.com/en-us/library/ms683223%28VS.85%29.aspx

    在“Windows 系统编程”一书的示例中,有一个程序使用该函数来准确检索您需要的内容(已用时间、内核时间、用户时间)。该程序名为“timep.exe”,可以在压缩示例存档中的 runX 子目录(X 来自编译中使用的 Visual Studio 版本)中找到。这是作者页面,您可以从那里下载该存档http://www.jmhartsoftware.com/,当然源代码也在那里,因此您可以确切地看到 timep.exe 是如何工作的。

    【讨论】:

      【解决方案2】:

      我同时使用了System.Diagnostics.ProcessGetProcessTimes 提供的时间来实现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}
      

      因为我正在创建一个 powershell 进程并在其中运行命令,所以实时时间大约为 11 秒(sleep 10),这并不是很完美。我会看看我是否可以为此实现一个 cmdlet 或其他东西。

      【讨论】:

      • 我对使用 Windows Powershell 非常陌生,您能解释一下我需要做什么才能使用您的 time 实现吗?
      【解决方案3】:

      您尝试测量的进程也可能在后台分叉和运行,这会导致 Measure-Command 测量中断。您可以使用 Start-Process-Wait 参数来获得您期望的全时测量。下面是一个示例,显示 stackoverflow.com 需要 34 秒才能关闭空闲连接:

      $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
      

      【讨论】:

        【解决方案4】:

        警告,PowerShell 提前。

        一些咖啡帮助我想出了这个:

        function time { $Command = "$args"; Measure-Command { Invoke-Expression $Command 2>&1 | out-default} }
        

        如果你想让它不输出任何内容,只需用 out-null 替换:

        function timequiet { $Command = "$args"; Measure-Command { Invoke-Expression $Command 2>&1 | out-null} }
        

        你可以这样使用它:

        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:\>
        

        【讨论】:

        • 我认为你没有回答问题
        猜你喜欢
        • 1970-01-01
        • 2011-05-24
        • 2018-01-11
        • 1970-01-01
        • 2010-09-08
        • 2012-09-01
        • 2011-03-25
        • 2016-10-02
        相关资源
        最近更新 更多