当输入通过管道传输或重定向到它时,sort / uniq命令的内部工作

时间:2017-04-25 05:06:49

标签: linux shell sorting unix pipe

在Linux中执行时,我一直在尝试理解下面命令中涉及的执行和内部数据结构和算法。

bzip -dc mybig.bz2 | cut -d ',' -f 1,2,4,5,9,10,12 | sort > output_file
  1. 当您将一个程序的输出传递给另一个程序时,中间结果存储在哪里?
    • 当我们有sort / uniq命令管道来接受来自前一个命令的输入时,是否能够与bzip2并行工作,可以sort排序而不需要一次输入所有输入吗?
    • 由于sort(gnu-coreutils)在内部进行合并排序,在执行期间排序的合并排序的中间结果,如果文件mybig.bz2的大小是20GB,如何排序管理所有中间结果磁盘这么大的文件?
  2. 如何比较以下两个不同shell脚本的I / O操作数,中间文件大小和cpu使用率(我正在寻找更多的理论推理而不是基准测试结果)?
  3. 使用重定向和中间文件。

    bzip -dc mybig.bz2 > temp1
    cut -d ',' -f 1,2,4,5,9,10,12 temp1 > temp2 
    sort temp2 > output_file
    

    使用管道。

    bzip -dc mybig.bz2 | cut -d ',' -f 1,2,4,5,9,10,12 | sort > output_file
    

    有没有更好的方法来使用shell,其中catcutsort并行运行(行缓冲)并且最小的磁盘I / O和cpu周期?

    任何帮助高度赞赏。

1 个答案:

答案 0 :(得分:0)

使用重定向和中间文件

bzip -dc mybig.bz2 > temp1
cut -d ',' -f 1,2,4,5,9,10,12 temp1 > temp2 
sort temp2 > output_file

我们假设mybig.bz2为1 GB,未压缩版本为10 GB。以上将是:

  • 读取1并写入10(bzip2 - > temp1)
  • 读取10并写入10(切割,我们假设切割尺寸基本相同)
  • 读取10,写入10,读取10并写入10(排序使用临时文件进行大排序)。

总磁盘I / O为1 + 10 + 10 + 10 + 10 + 10 + 10 + 10 = 71 GB。

使用管道

bzip -dc mybig.bz2 | cut -d ',' -f 1,2,4,5,9,10,12 | sort > output_file

在这里:

  • 读取1 GB(bzip2 - 数据未写入磁盘)
  • 从磁盘中读取任何内容(剪切将所有内容保存在内存中)
  • 写入10 GB,读取10 GB并写入10 GB(排序首先从内存读取,然后保存到磁盘上的临时文件,读取这些文件并写入输出)

总磁盘I / O为1 + 10 + 10 + 10 = 31 GB。

使用管道不会浪费任何东西。相反,如果bzip2与排序速度相同,则可以保持2个CPU并行运行。较新版本的排序也支持' - parallel = N'在多个CPU上分发排序。

如果排序的数据压缩得很好,您还可以使用--compress-program=PROG来压缩临时文件。如果您的CPU无论如何都处于空闲状态,这将非常有用。根据您闲置的CPU数量,您可以使用' pzstd',' pigz',' pbzip2',' pxz'。它们具有不同的压缩程度(从低到高)。

这样您就可以将磁盘I / O从31 GB降低到1 + 1 + 1 + 10.

管道中的中间结果不存储在任何地方。相反,它会在写入后立即读取。两个进程之间只有一个小缓冲区(通常大约为4-128 KB)。当缓冲区已满时,写入过程会阻塞,直到读取过程从缓冲区读取内容。这种技术可以在1 GB RAM和100 GB磁盘的系统上处理1 TB数据 - 只要数据在存储在磁盘上时就被压缩。