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

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使用-Sset运行相同的命令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)

所以我的猜测是根本没有调用压缩程序。

Pád*_*ady 5

这里没有转载?

$ 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 及以下。