【问题标题】:Process.Start() significantly slower than executing in consoleProcess.Start() 明显慢于在控制台中执行
【发布时间】:2014-11-27 10:48:26
【问题描述】:

我在使用 Process.Start() 执行 .exe 时遇到性能问题。 .NET 的执行时间大约是控制台的 5 倍。什么会导致这种情况?这是一个测试程序:

  public static void Main(string[] argv)
  {       
     for (int i = 0; i < 10; i++)
     {
        ProcessStartInfo psi = new ProcessStartInfo(ExePath, Args);
        Process ps = new Process {StartInfo = psi};
        Stopwatch sw = Stopwatch.StartNew();
        ps.Start();
        ps.WaitForExit();
        sw.Stop();
        Console.WriteLine(i+" Elapsed time: " + sw.ElapsedMilliseconds + "ms.");
        Thread.Sleep(1000);
     }
  }

结果是这样的:

 0 Elapsed time 4310ms.
 1 Elapsed time 4330ms.
 2 Elapsed time 4280ms.
 ...

在 cmd 窗口中运行它几乎立即返回(执行不到 1 秒)。尝试使用

在控制台中计时
> powershell Measure-Command { cmd /c start /wait %EXE% %ARGS% } 

显示执行时间约为 750 毫秒,快了 5-6 倍。不确定我做对了,但 750 毫秒感觉像是一个可能的执行时间。

起初我正在阅读 std 并认为它与此有关,请参阅例如Process takes longer to finish than in CMD 和类似问题。显然,在简单的测试程序中,我现在没有读取任何输出,只是在执行。

我已经排除了导致执行时间没有差异的可能原因:

  • 调试器/无调试器
  • .NET 主机进程的调试/发布版本
  • 工作目录
  • 宿主.NET进程平台Any/x86/x64(exe为原生x64)
  • UseShellExecute 真/假

我对可执行文件的了解(它是 rust 语句完成工具 'racer' https://github.com/phildawes/racer)是它会启动并打开大量文件。当来自 .NET 主机时,这是否重要,例如wrt。安全,导致减速?还有什么可能导致巨大的性能差异?

【问题讨论】:

  • 您的时间安排远不止开始这个过程。
  • @leppie 那会是什么?我在那里看不到更多。
  • 我无法想象创建这两个对象需要几秒钟。更像是微秒。
  • 这就是我的问题的答案,如果有任何理由创建进程(对象)需要 3 秒以上。正如预期的那样,在软件之外创建它的差异是微不足道的。编辑代码示例。
  • 哎呀,你成功了!二进制文件的版本略有不同,性能差异很大。什么面子。我希望你有一个我可以接受的答案,至少可以给你积分。感谢您的帮助!

标签: c# .net


【解决方案1】:

在这种情况下运行时间的差异是由于执行的 (racer.exe) 文件的不同版本造成的,与一个从 .NET 进程执行另一个从命令执行的事实无关线。

从 .NET 运行可执行文件应该没有区别,因为它只是使用系统调用来执行程序。

【讨论】:

  • 正是这个。任何性能差异应该只是因为输出流的读取方式(缓冲/阻塞)
  • 其实很惊讶我也遇到了这个问题。基本上是在做一个 process.start 并启动 exiftool。在内部运行的相同版本需要更长的时间来更新一个文件,而在 cmd 中运行相同的版本需要一秒钟。这里必须有一些错误。如果不需要,我可以提供更多
【解决方案2】:
    ps.WaitForExit();

这就是与众不同的声明。您的 cmd.exe 命令不会等待进程终止。删除 WaitForExit() 或使用“cmd /c start /wait %EXE% %ARGS%”来比较苹果和橘子。

或者换句话说,你没有衡量启动一个进程需要多长时间,你衡量的是进程运行了多长时间。

【讨论】:

  • 谢谢,这只是一个很小的区别。它仍然会在
  • 好吧,PowerShell 真的会自己等待吗?可能不会,通过删除 WaitForExit() 语句来获得“快速”版本。还有 Thread.Sleep(),那是没有意义的。
  • 我真正想做的是获得时间,直到它完成,即(它将一些输出写入标准输出然后退出)。如果我在控制台“通过眼睛”执行此操作,我至少可以看到它需要多长时间才能写入标准输出并将我返回到控制台,对于本机大约需要 1 秒,对于上述 .NET 包装器大约需要 4 秒。在 procmon 中查看后者,我可以看到从 .NET 调用本机(其事件的时间戳)exe 的实际执行时间超过 3 秒。如果我没有 WaitForExit() 它会报告一些微不足道的时间,然后等待 4 秒并写入标准输出。
  • 这与你启动的程序有关。我无法在不了解它的情况下做出任何体面的猜测,但是许多程序需要将 ProcessStartInfo.WorkingDirectory 属性设置为包含 .exe 的同一目录才能正常工作。
  • 是的,我在相同的环境中运行,至少 wrt。工作目录和环境变量:(
猜你喜欢
  • 2010-11-28
  • 2010-10-27
  • 2015-06-13
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 1970-01-01
  • 2011-07-19
相关资源
最近更新 更多