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

标签 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 的命令通过管道接受来自前一个命令的输入时,sort 是否能够与 bzip2 并行工作,sort 是否可以在不同时获得所有输入的情况下进行排序?
    • 由于 sort(gnu-coreutils) 在内部执行合并排序,执行期间合并排序的中间结果在哪里,假设文件 mybig.bz2 的大小为 20GB,排序如何管理所有如此巨大的文件在磁盘中的中间结果?
  2. 您如何比较以下两个不同 shell 脚本的 I/O 操作数、中间文件大小和 cpu 使用率(我正在寻找更多的理论推理而不是基准测试结果)?

使用重定向和中间文件。

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 周期?

非常感谢任何帮助。

最佳答案

使用重定向和中间文件

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 - 数据未写入磁盘)
  • 不从磁盘读取任何内容(cut 将所有内容保存在内存中)
  • 写入 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 数据 - 只要数据在存储在磁盘上时经过压缩。

关于linux - 当输入通过管道或重定向到它时,sort/uniq 命令的内部工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43602042/

相关文章:

Linux shell 脚本搜索/tmp 并附加或替换/etc/fstab 中的挂载选项

Javascript 根据类对 DIV 进行排序

c - 是否有充分的理由编写我自己的 daemonize 函数而不是使用 daemon(3)?

c - 回调函数内的同步问题

linux - 提高 avconv 负载和速度?

python - 如何在 txt 文件 python 中获取脚本的输出

linux - 需要帮助切割鱿鱼原木

linux - 如何动态链接automake中的库?

c++ - 将新值放入数组 C++ 时即时排序

Python numpy 将二维数组转换为已排序的一维数组