루프 대 확장 성능


9

아래 비교에 대한 전문가의 제안이 필요합니다.

루프를 사용한 코드 세그먼트 :

for file in `cat large_file_list`
do
    gzip -d $file
done

간단한 확장을 사용하는 코드 세그먼트 :

gzip -d `cat large_file_list`

어느 것이 더 빠를까요? 큰 데이터 세트를 조작해야합니다.


1
정답은 gzip시스템에서 시작하는 데 걸리는 시간 , 파일 목록의 파일 수 및 파일 크기에 따라 다릅니다.
Kusalananda

파일 목록에는 약 1000-10000 개의 파일이 있습니다. 크기는 몇 킬로바이트에서 500MB까지 다양합니다. 내 시스템에서 gzip 을 시작하는 데 시간이 얼마나 걸리는지 모르겠습니다 . 어떤 방법으로 확인?
레온

1
그렇다면 파일 이름길이에 따라 달라질 수 있습니다 . 파일 이름이 긴 경우 명령 대체로 인해 쉘이 실행하기에 너무 긴 명령 행이 발생하므로 루프없이 수행하려고하면 일부 시스템에서 "인수 목록이 너무 깁니다"오류가 발생할 수 있습니다. 목록의 파일 수에 의존하지 않으려면 루프를 사용하십시오. 수행 할 다른 처리와 비교하여 이러한 파일의 압축을 푸는 데 많은 시간을 소비하고 있습니까?
Kusalananda

Leon은 내 테스트 결과를 살펴 봅니다. "huge-arglist"는 설정에서 "loop"보다 20 배 빠릅니다.

프로세스 시작과 명령 행 길이 사이의 행복한 매체를 위해, 비슷한 것을 사용 xargs gzip -d < large_file_list하지만 파일 이름에서 공백을 조심하십시오.tr \\n \\0 large_file_list | xargs -0 gzip -d
w00t

답변:


19

합병증

다음은 때때로 작동합니다.

gzip -d `cat large_file_list`

세 가지 문제가 있습니다 ( bash대부분의 Bourne과 같은 쉘에서).

  1. 파일 이름에 공백 탭이나 줄 바꿈 문자가있는 경우 실패합니다 ( $IFS수정되지 않은 것으로 가정 ). 이것은 쉘의 단어 splitting 때문입니다 .

  2. 파일 이름에 glob-active 문자가 있으면 실패 할 수도 있습니다. 쉘이 파일 이름에 경로 이름 확장 을 적용하기 때문 입니다.

  3. 와 파일 이름 시작이 경우에도 실패합니다 -(경우 POSIXLY_CORRECT=1또는 경우에 그 첫 번째 파일에 적용) 모든 파일 이름입니다 -.

  4. 하나의 명령 행에 맞지 않는 파일 이름이 너무 많으면 실패합니다.

아래 코드는 위 코드와 동일한 문제가 있습니다 (4 번째 제외).

for file in `cat large_file_list`
do
    gzip -d $file
done

안정적인 솔루션

당신이 경우 large_file_list줄에 정확히 하나의 파일 이름을 가지고 있으며,라는 파일이 -그 (것)들의 사이에서하지 않고, 당신이 GNU 시스템에있어, 다음 사용

xargs -rd'\n' gzip -d -- <large_file_list

-d'\n'xargs각 입력 줄을 별도의 파일 이름으로 취급하도록 지시 합니다.

-rxargs입력 파일이 비어 있으면 명령을 실행하지 않도록 지시 합니다.

--이야기 gzip다음 인수들이 시작하는 경우에도 옵션으로 취급되지 않도록 -. -그래도 여전히 -호출 된 파일 대신 처리됩니다 -.

xargs각 명령 줄에 많은 파일 이름을 넣지 만 명령 줄 제한을 초과하는 파일 이름은 없습니다. 이렇게하면 gzip프로세스를 시작해야하는 횟수가 줄어들어 빠르게 진행됩니다. 파일 이름도 단어 분할경로 이름 확장 으로부터 보호됩니다 .


자세한 답변 감사합니다. 언급 한 3 가지 문제를 이해합니다. 파일 이름은 단순하며 목록이 20000까지 유지되므로 이러한 문제에 직면하지 않습니다. 내 질문은 기본적으로 두 세그먼트의 성능에 관한 것입니다. 감사.
레온

1
@Leon for루프는 가장 느리게 진행됩니다. 다른 두 가지 방법은 서로 속도가 매우 비슷합니다.
John1024

7
또한 잠재적 인 문제를 무시하지 마십시오. StackExchange에 대한 많은 질문 은 예상하지 못한 사람들에게 단어 분리 또는 경로 이름 확장 이 발생 했기 때문 입니다.
John1024

5
xargs적어도 GNU 버전에는 --arg-file옵션 (짧은 형식 -a) 이 있는 파일을 읽는 변형 이 있습니다 . 그래서 xargs -a large_file_list -rd'\n' gzip -d 대신 할 수 있습니다. 효과적으로, 차이는 사실을 제외하고,이 없다 <쉘 연산자 및 만들 것 xargs동안, (파일 "링크"쉘있는) 표준 입력에서 읽을 -a만들 것 xargs명시 적으로 문제의 파일 열기
세르지 Kolodyazhnyy

2
terdon은의 parallel여러 복사본을 실행하는 데 사용 하는 것에 대한 또 다른 의견에서 언급 gzip했지만 xargs(적어도 GNU 버전) 그 -P스위치도 있습니다. 차이가 생길 수있는 멀티 코어 머신에서. 그러나 감압이 어쨌든 완전히 I / O 바운드 일 수도 있습니다.
ilkkachu

12

나는 그것이 중요하다고 의심합니다.

목록 파일에 몇 개의 파일이 나열되어 있는지 모르고 파일 이름 중 이름에 공백이 있는지 (일반적으로) 알지 못하기 때문에 루프를 사용합니다. 매우 긴 인수 목록을 생성하는 명령 대체를 수행하면 생성 된 목록의 길이가 너무 길면 "인수 목록이 너무 깁니다"오류가 발생할 수 있습니다.

내 루프는 다음과 같습니다

while IFS= read -r name; do
    gunzip "$name"
done <file.list

또한 명령 후 데이터를 처리하기위한 명령을 삽입 할 수 gunzip있습니다. 실제로 데이터의 실제 내용과 수행해야 할 내용에 따라 파일에 전혀 저장하지 않고 처리 할 수도 있습니다.

while IFS= read -r name; do
    zcat "$name" | process_data
done <file.list

( process_data표준 입력에서 압축되지 않은 데이터를 읽는 파이프 라인이 있습니다)

데이터 처리가 압축 해제보다 시간이 오래 걸리면 루프가 더 효율적인지 아닌지에 대한 문제가 관련이 없게됩니다.

이상적으로 는 파일 이름 목록을 처리하지 않고 파일 이름 글 로빙 패턴을 사용하는 것이 좋습니다.

for name in ./*.gz; do
    # processing of "$name" here
done

여기서 ./*.gz관련 파일과 일치하는 몇 가지 패턴입니다. 이런 식으로 파일 수나 파일 이름에 사용 된 문자에 의존하지 않습니다 (개행 또는 기타 공백 문자를 포함하거나 대시로 시작하는 등).

관련 :


5

이 두 가지 중에서 한 번만 실행하면 모든 파일이 단일 호출로 전달 된 gzip것이 더 빠를 수 있습니다 gzip. 즉, 명령이 전혀 작동하지 않으면 다른 경고에 대한 답변을 참조하십시오.

그러나, 나는 생각 나게하고 싶습니다 최적화의 황금률 : 음주 조기에 그것을하지.

  1. 그것이 문제라는 것을 알기 전에 그런 종류의 것을 최적화하지 마십시오.

    프로그램의이 부분이 오래 걸립니까? 큰 파일의 압축을 풀면 어쨌든 그렇게해야하므로 대답하기 쉽지 않을 수 있습니다.

  2. 법안. 실제로 가장 확실한 방법입니다.

    자신의 눈으로 (또는 자신의 스톱워치로) 결과를 볼 수 있으며, 인터넷에서 무작위로 응답하지 않는 상황에 적용됩니다 . 두 변형을 스크립트에 넣고 time script1.sh, 및을 실행하십시오 time script2.sh. (빈 압축 파일 목록을 사용하여 오버 헤드의 절대량을 측정하십시오.)


0

디스크가 얼마나 빠릅니까?

모든 CPU를 사용해야합니다.

parallel -X gzip -d :::: large_file_list

따라서 한계는 디스크 속도가 될 것입니다.

다음을 사용하여 조정할 수 있습니다 -j.

parallel -j50% -X gzip -d :::: large_file_list

이렇게하면 작업의 절반이 이전 명령과 병렬로 실행되고 디스크에 대한 부담이 줄어들 기 때문에 디스크에 따라 더 빠를 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.