r0g*_*r0g 3 compression gnu sort
我正在对大文件(>100Go)进行排序,并且为了减少在磁盘写入上花费的时间,我正在尝试使用 GNU sort 的--compress-program
参数。(相关:如何对大文件进行排序?)
但是,在某些情况下似乎只有第一个临时文件被压缩。我想知道为什么,以及我可以做些什么来压缩所有临时文件。
我在用:
sort (GNU coreutils) 8.25
lzop 1.03
/ LZO library 2.09
重现问题的步骤:
你需要一些东西,比如 ~15Go 空闲空间,~10Go ram,一段时间
首先,使用以下 C 代码创建一个 10Go 文件:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned long n;
unsigned char i;
srand(42);
for(n = 0; n < 1000000000; n++) {
for(i = 0; i < 3; i++) {
printf("%03d", rand() % 1000);
}
printf("\n");
}
fflush(stdout);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并运行它:
$ gcc -Wall -O3 -o generate generate.c
$ ./generate > test.input # takes a few minutes
$ head -n 4 test.input
166740881
241012758
021940535
743874143
Run Code Online (Sandbox Code Playgroud)
然后,开始排序过程:
$ LC_ALL=C sort -T . -S 9G --compress-program=lzop test.input -o test.output
Run Code Online (Sandbox Code Playgroud)
一段时间后,暂停进程,并列出在同一文件夹中创建的临时文件(由于-T .
):
$ ls -s sort*
890308 sortc1JZsR
890308 sorte7O878
378136 sortrK37RZ
$ file sort*
sortc1JZsR: ASCII text
sorte7O878: ASCII text
sortrK37RZ: lzop compressed data - version 1.030, LZO1X-1, os: Unix
Run Code Online (Sandbox Code Playgroud)
似乎只有sortrK37RZ
(第一个临时创建的)已被压缩。
[编辑]sort
使用-S
set运行相同的命令7G
很好(即所有临时文件都被压缩),而8G
存在问题。
[编辑] lzop 不为其他临时调用
我尝试并使用以下脚本作为以下脚本的包装器lzop
:
#!/bin/bash
set -e
echo "$$: start at $(date)" >> log
lzop $@
echo "$$: end at $(date)" >> log
Run Code Online (Sandbox Code Playgroud)
这是log
文件的内容,当几个临时文件写入磁盘时:
11109: start at Sun Apr 10 22:56:51 CEST 2016
11109: end at Sun Apr 10 22:57:17 CEST 2016
Run Code Online (Sandbox Code Playgroud)
所以我的猜测是根本没有调用压缩程序。
这里没有转载?
$ shuf -i1-10000000 > t.in
$ sort -S50M -T. t.in --compress-program=lzop # ^z
$ file sort* | tee >(wc -l) > >(grep -v lzop)
7
$ fg # ^c
$ sort --version | head -n1
sort (GNU coreutils) 8.25
Run Code Online (Sandbox Code Playgroud)
我猜测的问题是,由于内存大小较大,无法 fork() 压缩过程,然后又回到标准写入。IE sort(1) 使用 fork()/exec() 理想情况下它应该使用 posix_spawn() 来更有效地分叉压缩过程。现在 fork() 是 CoW,但是在为如此大的过程准备相关的会计结构方面仍然存在开销。在 sort(1) 的未来版本中,我们将使用 posix_spawn() 来避免这种开销(从 2.23 版开始,glibc 才刚刚获得了 posix_spawn() 的可用实现)。
与此同时,我建议使用更小的 -S。也许 -S1G 及以下。