为什么“读取”文件的每一行比“xargs”快得多

为什么“读取”文件的每一行比“xargs”快得多

我有一个很大的输入文件,其中包含 30M 行,\r\n.我决定做一些愚蠢的事情,并比较通过read -r比较计算所有行的速度xargs(剥离第\r一个,因为xargs似乎无法分割多个字符)。这是我的两个命令:

time tr -d '\r' < input.txt | xargs -P 1 -d '\n' -I {} echo "{}" | wc -l
time while read -r p || [ -n "$p" ]; do echo "$p"; done < input.txt | wc -l

这里,第二个解决方案是很多快点。这是为什么?

请注意,我知道这不是计算文件行数的正确方法。这个问题只是出于我的观察兴趣。

答案1

是的,正如您所怀疑的,实际上与默认命令xargs -P 1 -d '\n' -I {} echo "{}"相同,它将分叉一个进程并在子进程中执行独立进程,同时等待其在父进程中为每行输入终止。xargs -rd '\n' -n1echoecho

因此,这比在同一个 shell 进程中使用低效的read内置函数和所有内置函数要多得多的工作。echo

xargs如果您使用 busybox而不是 GNU ,xargs它(至少在某些配置和最新版本中)将echo在内部调用 busybox 而无需分叉进程,您会注意到它会比bash循环快得多。

为了进行更相关的比较,您应该比较:

tr -d '\r' | xargs -rd'\n' -n1

tr -d '\r' |
  while IFS= read -r line || [ -n "$line" ]; do
   /bin/echo "$line"
  done

这可能会给您带来类似的结果,因为大部分时间将花费在分叉进程和执行独立的echo.

在这里,关于输出seq 3e7和测量pv -al > /dev/null(以每秒a平均线数来测量吞吐量),我得到了解决方案:l

  • busybox xargs 为 1.12M/s
  • 带有内置 echo 的 bash 循环速度为 70k/s
  • GNU xargs 为 860/s
  • 850/s 用于带有 /bin/echo 的 bash 循环

相关内容