管道功能的效率

时间:2017-06-26 18:36:22

标签: bash function pipe eval

我写了一个函数来帮助管理其他功能。但它严重缺乏效率。

首先我写这个函数来包装其他人。它从standard input读取并将指定的function应用于每个输入:

function func_pipe() {
  local func="$1" && shift
  while ifs='' read -r line || [[ -n "$line" ]]; do
    $func $line
  done
}

我定义了一个用于测试目的的模式:

PATTERN="mypattern"

我创建了一个10k行的大文件进行测试:

### Create big file
time for i in $(seq 1 10000); do 
  echo "$i - here I write the pattern $PATTERN for testing purpose."; 
done > bigfile.txt

real    0m38.234s
user    0m10.245s
sys 0m20.050s

我编写了处理输入的函数:

function process1() {
  echo -e "$@" | egrep "$PATTERN"
}

我处理文件以搜索模式。我使用func_pipe来处理standard input。 :

echo -e "\n[Testing with pipes]"
time cat bigfile.txt \
 | func_pipe process1 \
 | func_pipe process1 \
 | wc -l

real    1m23.898s
user    1m16.992s
sys 1m54.495s

现在我将在一个字符串中构建我的命令,稍后再evaluate

首先,我编写了一个类似的处理函数,它将在一个字符串中打印管道。请注意使处理功能不同的下划线:

function _process1() {
  echo " | grep \"\$PATTERN\""
}

我定义了我的命令和处理字符串:

cmd="cat bigfile.txt"
cmd_process="$(_process1)$(_process1) | wc -l"

我测试它们:

echo -e "\n[Testing with eval]"
time eval "${cmd}${cmd_process}"

real    0m0.014s
user    0m0.015s
sys 0m0.013s

它瞬间完成了它。因此,似乎管道功能和读取每个标准输入的效果确实不高效。至少,我想这个问题来自我的实施。我的目标是使它们与管道unix命令(cutsedetc)一样高效。我相信那些命令也是从stdin读取的,所以我是缺少一些方法的人。缺少什么来改善我的包装功能?

2 个答案:

答案 0 :(得分:2)

你的两种方法有一个主要区别:第二种方法只产生一个grep进程,它将从stdin读取整个文件,而你的第一种方法将为每个输入行产生一个grep进程。

我怀疑这是你观察到的差异的原因。产生一个过程很便宜但不是免费的。

由于shell(逐行读取+将每一行传递给子进程),第一个版本也会出现更多开销。

如果你想减少这种开销,你的func_pipe应该将整个标准输入传递给process1函数,而不是逐行分割它。

答案 1 :(得分:1)

只是读入bash的速度很慢,每个行也会分叉一个新进程。