如何计算分叉(子?)进程的数量

彼得·V·莫希(PeterV.Mørch)

有人编写了一些bash脚本(TM),该脚本分叉了很多子进程。它需要优化。但我正在寻找一种方法来衡量问题的“严重程度”。

我/如何获得一个计数,说明该脚本全部/递归分叉了多少个子流程?

这是现有分叉代码的简化版本-一个穷人的grep:

#!/bin/bash

file=/tmp/1000lines.txt
match=$1

let cnt=0
while read line
do
    cnt=`expr $cnt + 1`
    lineArray[$cnt]="${line}"
done < $file
totalLines=$cnt

cnt=0
while [ $cnt -lt $totalLines ]
do
    cnt=`expr $cnt + 1`
    matches=`echo ${lineArray[$cnt]}|grep $match`
    if [ "$matches" ] ; then
        echo ${lineArray[$cnt]}
    fi
done

$1在1000行输入中查找脚本需要20秒这段代码分叉了太多的子流程。在实际代码,有较长的配管(例如progA | progB | progC)使用每行操作grepcutawksed等。

这是一个忙碌的系统,正在运行许多其他内容,因此,对脚本运行时整个系统上有多少个进程进行了分叉的计数对我来说很有用,但我宁愿选择一个此脚本及其后代启动的进程。而且我想我可以自己分析脚本并对其进行计数,但是该脚本又长又相当复杂,因此,如果可能的话,我想使用此计数器对其进行调试。

澄清:

  • 我不是$$在任何给定时间(例如,通过ps寻找进程数,而是在脚本的整个生命周期内运行的进程数。
  • 我也没有在寻找这个特定示例脚本的更快版本(我可以做到)。我正在寻找一种方法,以确定先优化30多个脚本中的哪个以使用bash内置函数。

您可以fork简单地捕获SIGCHLD信号来计算ed过程。如果您可以编辑脚本文件,则可以执行以下操作:

set -o monitor # or set -m
trap "((++fork))" CHLD

因此fork变量将包含分叉数。最后,您可以打印以下值:

echo $fork FORKS

对于1000行输入文件,它将打印:

3000 FORKS

此代码分叉有两个原因。一个一个expr ...,一个一个`echo ...|grep...`因此,在while循环读取中,它fork是每次读取一行时所用的时间。在处理while循环中,它fork是2次(一次是因为,expr ...一次是`echo ...|grep ...`)。因此,对于1000行文件,它会分叉3000次。

但是,这不完全正确!它只是调用外壳程序完成的分叉。有更多的派生,因为`echo ...|grep...`派生启动来运行此代码。但是之后也有两次分叉:一次为echo,一次为grep因此实际上是3fork秒,而不是1秒。所以它是5000福克斯,而不是3000。

如果您还需要计算叉子(叉子...)的叉子(或者您无法修改bash脚本,或者您希望它从其他脚本中执行),则可以使用更精确的解决方案

strace -fo s.log ./x.sh

它将打印如下行:

30934 execve("./x.sh", ["./x.sh"], [/* 61 vars */]) = 0

然后,您需要使用类似这样的数字来计数唯一的PID(第一个数字是PID):

awk '{n[$1]}END{print length(n)}' s.log

如果使用此脚本,我会得到5001(+1是原始脚本的PID )。

评论

实际上,在这种情况下,fork可以避免所有

代替

cnt=`expr $cnt + 1`

使用

((++cnt))

代替

matches=`echo ${lineArray[$cnt]}|grep $match`
if [ "$matches" ] ; then
    echo ${lineArray[$cnt]}
fi

您可以使用的内部模式匹配:

[[ ${lineArray[cnt]} =~ $match ]] && echo ${lineArray[cnt]}

注意 =~使用ERE而不是RE(例如grep)。因此它的行为类似于(或grep -E),而不是

我认为定义lineArray不是没有意义的(否则在读取循环中可以测试匹配并且lineArray不需要),并且它也可以用于其他目的。在这种情况下,我可能会建议使用较短的版本:

readarray -t lineArray <infile 

for line in "${lineArray[@]}";{ [[ $line} =~ $match ]] && echo $line; }

第一行读取完整的内容infilelineArray没有任何循环。第二行是逐元素处理数组。

措施

1000行的原始脚本(在):

$ time ./test.sh
3000 FORKS

real    0m48.725s
user    0m14.107s
sys     0m30.659s

修改版

FORKS

real    0m0.075s
user    0m0.031s
sys     0m0.031s

3000 FORKS

real    0m4.745s
user    0m1.015s
sys     0m4.396s

FORKS

real    0m0.028s
user    0m0.022s
sys     0m0.005s

因此,此版本完全不使用fork(或clone)。我可能建议仅将此版本用于较小的文件(<100 KiB)。在其他情况下, over执行纯解决方案。但这应该通过性能测试进行检查。

对于上的一千行,我得到了以下内容:

$ time grep Solaris infile # Solaris is not in the infile

real    0m0.001s
user    0m0.000s
sys     0m0.001s

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何计算系统中睡眠进程的数量?

来自分类Dev

如何以与Linux系统调用的fork()相同的意义来分叉/克隆相同的Node子进程?

来自分类Dev

Nodejs分叉的子进程立即退出,状态码为8

来自分类Dev

分叉并等待子进程似乎根本不等待

来自分类Dev

如何计算包含子进程的进程ID的已执行指令数

来自分类Dev

如何计算精灵数量

来自分类Dev

如何计算硬币数量?

来自分类Dev

如何计算精灵数量

来自分类Dev

如何检测系统是否支持python中的进程分叉?

来自分类Dev

如何解决Python分叉进程中OpenSSL的PRNG限制?

来自分类Dev

如何继续分叉进程直到我“几乎”耗尽内存

来自分类Dev

如何设置用于集成测试的分叉JVM的数量?

来自分类Dev

用C分叉进程

来自分类Dev

限制分叉的进程数

来自分类Dev

无法杀死分叉的进程

来自分类Dev

当分叉的进程死亡时,该进程中的分离线程会如何处理?

来自分类Dev

当分叉的进程死亡时,该进程中的分离线程会如何处理?

来自分类Dev

计算属于回文的子串的数量

来自分类Dev

计算属于回文的子串的数量

来自分类Dev

我应该用exit()终止一个分叉的子进程吗?

来自分类Dev

分叉后立即调用exec()的子进程怎么不需要父地址空间的单独副本?

来自分类常见问题

如何从父进程获取子进程

来自分类Dev

如何同时杀死进程和子进程?

来自分类Dev

如何计算给定数组中包含子字符串的单元格数量?

来自分类Dev

如何计算特定值的数量

来自分类Dev

如何计算失败的诺言数量?

来自分类Dev

如何计算失败的诺言数量?

来自分类Dev

如何计算特定值的数量

来自分类Dev

netmask:如何计算网络数量?

Related 相关文章

热门标签

归档