【问题标题】:perl: long delays during repeated system callsperl:重复系统调用期间的长时间延迟
【发布时间】:2020-11-02 21:07:51
【问题描述】:

不确定这是 perl 问题、cywin 问题还是 Windows 问题:

我在 Windows8 下的 cygwin 中运行 perl。我们有大量用于单个任务的小脚本,我最近编写了一个顶级脚本,它通过“系统”调用反复调用其中的几个脚本。所有脚本自己运行完美,但执行只是在块中发生,即顶级脚本开始运行,大约 10 秒后它停止并且计算机再空闲 10-15 秒,然后再次启动 10 秒,等等。除了这个脚本之外,PC 只运行通常的 Windows 后台进程,即顶级脚本是唯一导致显着 CPU 负载的进程。

脚本太长,无法在此处显示,但本质上是由结构组成,其中一些变量在循环中定义,然后通过 sprintf 字符串组合以调用脚本,就像下面的 sn-p:

(...)
foreach $period (@periods)
{
    foreach $wt (@wtlist)
    {   
        foreach $type ('WT', 'Ref')
        {
            $out=1;
            $dir1=0*$sectorwidth;
            $dir2=1*$sectorwidth;
            $addfile0 = sprintf("%s/files/monthly_recal/%s%s_from%s.%s_%03d.da1", $workingdir_correl, $nameRoot, $wt, $type, $period, $dir1 ) ;
            $addfile1 = sprintf("%s/files/monthly_recal/%s%s_from%s.%s_%03d.da1", $workingdir_correl, $nameRoot, $wt, $type, $period, $dir2 ) ;
            if (-e $addfile0 && -e $addfile1)
            {
                $cmd = sprintf ( "perl ../00Bin/add_sort_ts.pl $addfile0 $addfile1 %s/files/monthly_recal/tmp/%s%s_from%s.%s.out%02d 0 $timeStep\n", $workingdir_correl, $nameRoot, $wt, $type, $period,  $out ) ;
                print ($cmd);
                system ( $cmd ) ;
            }
        }
    }
}
(...)

定义了所有变量(简单的字符串或整数),并且各个调用都正常工作。

当这个顶级脚本运行时,它会一个接一个地运行几个循环迭代,所以我认为这不是被调用脚本的启动延迟问题。对我来说,它看起来更像是 Windows 连续拒绝了太多的系统调用。我有其他没有“系统”调用的 perl 脚本,它们运行了 10 分钟而没有显示这种间歇性行为。

我没有真正的线索去哪里寻找,所以任何建议都将不胜感激。顶层脚本的整个执行时间可能需要几个小时,因此这里的任何改进都会大大提高效率!

--更新:从下面的讨论到 Hakon 的回答,原来问题出在用于运行 perl 脚本的 shell 上——当代码从 Windows cmd 或非登录 shell,但不是从登录 shell 显式运行时(例如,使用 bash --login 或盯着 mintty - 时)。我将很快打开另一个线程来澄清为什么会发生这种情况......感谢这里的所有贡献者!

【问题讨论】:

  • 请出示剧本。
  • 你的机器上是否运行着类似“AppSense”的东西来拦截任何进程的创建?
  • 据我所知,TaskManager 没有显示任何名为“AppSense”的内容。 AFAIK,系统几乎是标准的 Windows。
  • “我们有大量的小脚本”:代码只显示了一个脚本。这个脚本add_sort_ts.pl 长什么样子?
  • 它读取由测量时间序列组成的两个输入文件($addfile0,$addfile1)(即每行以时间戳开头,后跟一组数据),并将所有时间戳按顺序排列命令。排序的时间序列被写入目录 %s/files/monthly_recal/tmp/ 中的输出文件。在排序过程中使用参数 '0' 和 $timestep。 -- 我本可以显示其他代码 sn-ps 调用其他脚本对时间序列数据执行不同操作,这些操作显示相同的问题行为,所以我认为这是顶级脚本的问题,而不是被调用脚本的问题。

标签: windows perl cygwin delay


【解决方案1】:

你能试着把你的问题简化一点吗?这将有助于更轻松地定位问题。例如,以下在 Windows 10、Strawberry Perl 5.30 上运行的代码(从 CMD 而非 Cygwin 运行)显示没有问题:

use strict;
use warnings;
for my $i (1..10) {
    system 'cmd.exe /c worker.bat';
}

用一个简单的worker.bat 喜欢:

@echo off
echo %time%
timeout 5 > NUL
echo %time%

运行 Perl 脚本的输出是:

10:35:00.71
10:35:05.18
10:35:05.22
10:35:10.17
10:35:10.22
10:35:15.15
10:35:15.19
10:35:20.19
10:35:20.23
10:35:25.15
10:35:25.20
10:35:30.16
10:35:30.21
10:35:35.14
10:35:35.18
10:35:40.16
10:35:40.20
10:35:45.16
10:35:45.21
10:35:50.15

显示system 调用之间没有延迟。

【讨论】:

  • 即使我们增加到 2500 次迭代,这个设置也能正常工作。但是,当脚本调用另一个 perl 脚本而不是批处理文件(例如通过system ("perl ./worker.pl");)并且worker.pl 仅包含一个简单的打印命令(例如print "1 ";)时,问题再次出现。然后,操作在大约 1150 次迭代后停止(在我的机器上大约 25 秒),再暂停 25 秒,然后执行下一个 ca。 1150 次迭代。
  • @vob 好的,很有趣。可能是缓冲区问题让我检查一下
  • 您要打印到 cygwin 终端窗口吗? (简单的打印命令)。它在 CMD 终端窗口中工作正常(没有延迟)
  • 不,我从 cmd 窗口调用它,并且输出也在那里。我的 Windows %PATH% 中有 cygwin /bin/ 目录。
  • 原来问题不在于代码,而在于终端模拟器。实际上,我是从 Windows 'cmd' 窗口运行上述所有代码的;这是因为 cygwin 目录在我的 %PATH% 中。但是,当我从“Cygwin 终端”(实际上是薄荷糖)运行相同的代码时,没有更多的间歇性,并且没有 bash 绕道的系统调用大约需要一半的时间,正如预期的那样。 -- 非常感谢所有分享他们的想法和建议的人,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2019-06-28
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
相关资源
最近更新 更多