subprocess.Popen在WSL Linux上花费的时间太长

时间:2018-11-18 09:59:10

标签: python subprocess windows-subsystem-for-linux

我有这个subprocess.Popen()上下文管理器:

with Popen(
    args=command, shell=False, stdout=PIPE, bufsize=1, universal_newlines=True
) as process:

    # TIMING
    start = timer()
    lines = list(process.stdout)
    end = timer()
    print('Time taken:', end - start) # 53.662078000000065 seconds -> Linux

    for _ in tqdm(iterable=lines, total=len(lines)):
        sleep(0.1)

if process.returncode != 0:
    raise CalledProcessError(returncode=process.returncode, cmd=process.args)

在WSL Linux环境中运行时,似乎需要53秒才能处理list(process.stdout)。但是,当我在Windows环境中运行它时,只需要0.6秒。我发现奇怪的是,为什么时间如此不同。

我尝试改用subprocess.run()subprocess.check_output(),但是在处理tqdm()循环之前,它们仍然导致相同的长时间滞后。

我在这里错过了什么吗?我尝试查看文档以了解在Windows vs WSL Linux环境中使用subprocess.Popen()有什么区别,但是我仍然不确定问题是什么。也许list(process.stdout)在这里是不必要的,还有一种更好的方法来存储来自stdout的行。

任何一种指导在这里都将非常有帮助。

2 个答案:

答案 0 :(得分:1)

用于Linux的Windows子系统有点垃圾。它有很多很多错误,并且比需要的要慢得多。这只是另一个错误。以下是一些可能的瓶颈:

  • WSL中的慢上下文切换。
  • WSL没有注意到等待管道的整个过程意味着应该立即运行管道的另一端。
  • 子进程被懒惰地执行。
  • Windows需要花一些时间才能确定它需要使用wsl.exe来启动程序(感谢RoadRunner!)
  • Windows的常规开销,再加上Linux的常规(相对较小)开销。
  • Ubuntu发行版选择不当,导致许多不必要的服务在systemd(?)中运行
  • Windows出于未知原因决定在子进程之前运行其他内容。
  • Windows子系统中针对Linux开发人员的蓄意恶意,旨在通过设置稻草人来“证明” Windows是高级操作系统。太傻了。

Python代码没有任何问题,这会使它变慢。

答案 1 :(得分:0)

您将需要使用WSL2重新评估2019年第三季度的性能问题。

请参见 Announcing WSL 2 中的“ Craig Loewen

  

这种新架构的变化将实现:大幅提高文件系统性能,以及完全的系统调用兼容性,这意味着您可以在WSL 2中运行更多Linux应用程序,例如Docker。

     

文件密集型操作,例如git clonenpm installapt updateapt upgrade等,都将明显更快。
  实际速度的提高将取决于您正在运行的应用程序以及它与文件系统的交互方式。
  在进行压缩的tarball打包后,我们进行的初始测试使WSL 2的运行速度比WSL 1快20倍,而使用git clonenpm installcmake时,WSL 2的运行速度要快2-5倍。在各种项目上。

     

Linux二进制文件使用系统调用来执行许多功能,例如访问文件,请求内存,创建进程等等。
  在WSL 1中,我们创建了一个转换层,用于解释许多这些系统调用,并允许它们在Windows NT内核上工作。但是,实现所有这些系统调用具有挑战性,导致某些应用程序无法在WSL 1中运行。
  现在,WSL 2包含了自己的Linux内核,它具有完全的系统调用兼容性