我正在对大文件(>100Go)进行排序,为了减少磁盘写入所花费的时间,我尝试使用 GNU sort 的--compress-program
参数。 (有关的:大文件如何排序?)
然而,在某些情况下,似乎只有第一个临时数据被压缩。我想知道为什么,以及我可以做什么来压缩所有临时文件。
我在用:
sort (GNU coreutils) 8.25
lzop 1.03
/LZO library 2.09
重现问题的步骤:
您将需要大约 15Go 的可用空间,大约 10Go 的内存,一段时间
首先,使用以下 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;
}
并运行它:
$ gcc -Wall -O3 -o generate generate.c
$ ./generate > test.input # takes a few minutes
$ head -n 4 test.input
166740881
241012758
021940535
743874143
然后,开始排序过程:
$ LC_ALL=C sort -T . -S 9G --compress-program=lzop test.input -o test.output
一段时间后,挂起该进程,并列出在同一文件夹中创建的临时文件(由于-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
似乎只有sortrK37RZ
(第一个临时创建的)被压缩了。
[编辑]在存在问题的情况下,运行相同的sort
命令并-S
设置为7G
就可以了(即所有临时文件都被压缩) 。8G
[编辑] lzop 不被其他临时调用
我尝试并使用以下脚本作为包装lzop
:
#!/bin/bash
set -e
echo "$$: start at $(date)" >> log
lzop $@
echo "$$: end at $(date)" >> log
log
以下是将多个临时文件写入磁盘时的文件内容:
11109: start at Sun Apr 10 22:56:51 CEST 2016
11109: end at Sun Apr 10 22:57:17 CEST 2016
所以我的猜测是压缩程序根本没有被调用。
答案1
这里不转载吗?
$ 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
我猜测问题是由于内存大小较大而无法 fork() 压缩过程,然后又回到标准写入。 IE sort(1) 正在使用 fork()/exec(),而理想情况下它应该使用 posix_spawn() 来更有效地分叉压缩过程。现在 fork() 是 CoW,但是为如此大的进程准备关联的记账结构仍然存在开销。在 sort(1) 的未来版本中,我们将使用 posix_spawn() 来避免这种开销(从版本 2.23 开始,glibc 才刚刚获得了 posix_spawn() 的可用实现)。
同时我建议使用更小的-S。也许-S1G及以下。