GNU sort --compress-program 仅压缩第一个临时文件

GNU sort --compress-program 仅压缩第一个临时文件

我正在对大文件(>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及以下。

相关内容