GNU sort --compress-program은 첫 번째 임시 파일만 압축합니다.

GNU sort --compress-program은 첫 번째 임시 파일만 압축합니다.

--compress-program나는 큰 파일(>100Go)을 정렬하고 있는데, 디스크에 쓰는 데 소요되는 시간을 줄이기 위해 GNU sort 매개변수를 사용하려고 합니다 . (관련된:대용량 파일을 정렬하는 방법은 무엇입니까?)

하지만 어떤 경우에는 첫 번째 임시 데이터만 압축되는 것 같습니다. 이유와 모든 임시 파일을 압축하기 위해 무엇을 할 수 있는지 알고 싶습니다.

나는 다음을 사용하고 있습니다 :

  • 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

문제는 큰 메모리 크기로 인해 압축 프로세스를 포크()한 다음 표준 쓰기로 돌아갈 수 없다는 것입니다. IE sort(1)는 이상적으로 압축 프로세스를 보다 효율적으로 분기하기 위해 posix_spawn()을 사용해야 할 때 fork()/exec()를 사용하고 있습니다. 이제 fork()는 CoW이지만 이러한 대규모 프로세스에 대한 관련 회계 구조를 준비하는 데 여전히 오버헤드가 있습니다. sort(1)의 향후 버전에서는 이 오버헤드를 피하기 위해 posix_spawn()을 사용할 것입니다(glibc는 버전 2.23부터 posix_spawn()의 사용 가능한 구현을 얻었습니다).

또한 더 작은 -S를 사용하는 것이 좋습니다. 어쩌면 - S1G 이하.

관련 정보