CPU 및 하드 드라이브 성능이 최대치가되지 않더라도 gzip이 왜 느립니까?


14

압축하려는 JSON 파일 (각각 20GB)이 있습니다 gzip.

gzip file1.json

이것은 하나의 완전한 CPU 코어를 차지합니다.

약 25MB / s (체크 인됨 atop)를 처리하고 하드 드라이브는 125MB / s를 읽을 수 있으며 3 개의 무료 프로세서 코어가 있으므로 여러 파일을 병렬로 압축 할 때 속도가 향상 될 것으로 예상됩니다. 그래서 다른 터미널에서 실행합니다.

gzip file2.json
gzip file3.json
gzip file4.json

놀랍게도 내 처리량이 증가하지 않습니다. CPU는 각 코어에서 약 25 %이며 HD는 여전히 25MB / s로만 읽습니다.

왜 그리고 어떻게 해결해야합니까?

답변:


17

나는 그것을 발견했다 :

그 이유는 매우 낮은 버퍼 크기gzip 에서 작동합니다 (요즘 CPU 속도 대 HD 탐색 속도 측면에서) .

입력 파일에서 몇 KB를 읽고 압축하여 출력 파일로 플러시합니다. 하드 드라이브 탐색이 필요하다는 사실을 감안하면 초당 몇 가지 작업 만 수행 할 수 있습니다.

내 공연이 확장되지 않은 이유는 이미 gzip미친 듯이 추구 했기 때문 입니다.


유닉스 buffer유틸리티 를 사용 하여이 문제를 해결했습니다 .

buffer -s 100000 -m 10000000 -p 100 < file1.json | gzip > file1.json.gz

gzip으로 보내기 전에 많은 입력을 버퍼링함으로써 작은 탐색 수를 크게 줄일 수 있습니다. 옵션 :

  • -s그리고 -m버퍼의 크기를 지정할 수 있습니다 (I는 생각 이 확실 KB에 있지만)
  • -p 100 버퍼가 100 % 채워지면 데이터가 gzip으로 만 전달되도록합니다.

이 중 4 개를 병렬로 실행하면 예상대로 4 * 25MB / s 처리량을 얻을 수 있습니다.


gzip을 사용하여 버퍼 크기를 늘릴 수없는 이유가 여전히 궁금합니다.이 방법으로 회전 디스크에서 실행하면 꽤 쓸모가 없습니다.

편집 : 압축 프로그램 동작을 몇 가지 더 시도했습니다.

  • bzip2 더 강력하고 더 CPU 집약적 인 압축으로 인해 2MB / s 만 처리
  • lzop 더 큰 버퍼 허용 : 코어 당 70MB / s

dd똑같이 할 수 있습니까 ?
Simon Kuang

@SimonKuang 옵션으로도 dd똑같이 할 수 있다고 생각합니다 bs=.
nh2

단일 파일의 경우 블록 크기가 단일 CPU 코어와 드라이브의 IOPS를 완전히 활용한다는 흥미로운 우연의 일치처럼 들립니다.
Dave L.

3

6.172에 대한 MIT OpenCourseware에서 "소프트웨어 시스템의 성능 엔지니어링"의 첫 5 개 강의를 살펴본 후, Linux 성능 분석기 'perf'를 약간 큰 테스트 파일에서 실행했습니다. 결과는 하나의 명령이 이전 명령의 결과를 기다려야하는 파이프 라인 정지를 보여줍니다.

       │         while (lookahead != 0) {                                                                
       │             /* Insert the string window[strstart .. strstart+2] in the                          
       │              * dictionary, and set hash_head to the head of the hash chain:                     
       │              */                                                                                 
       │             INSERT_STRING(strstart, hash_head);                                                 
  2.07 │       movzbl 0x8096d82(%edx),%eax                                                               
  3.99 │       mov    %edx,%ebp                                                                          
       │       shl    $0x5,%ecx                                                                          
  0.03 │       and    $0x7fff,%ebp                                                                       
  1.94 │       xor    %ecx,%eax                                                                          
  1.43 │       and    $0x7fff,%eax                                                                       
  2.01 │       mov    %eax,0x805e588                                                                     
  2.40 │       add    $0x8000,%eax                                                                      
  0.88 │       movzwl 0x8062140(%eax,%eax,1),%ecx                                                        
 23.79 │       movzwl %cx,%edi                                                                           
       │             /* Find the longest match, discarding those <= prev_length.  

두 번째 마지막 명령은 복사 중이며 마지막 명령은 레지스터에 데이터를 사용할 준비가 %ecx될 때까지 기다려야합니다 (파이프 라인 스톨) %cx. 이 파이프 라인 스톨은 포함 루프를 유지합니다.

이것은 실제로 모호한 '구식'C 프로그래밍 스타일의 결과입니다.


1

멀티 코어 / 하이퍼 스레딩 CPU에서 또 다른 수준의 속도를 낼 수있는 팁 :
(우분투를 가정)

sudo apt-get install moreutils

moreutils에는 "gnu parallel"이 포함되어 있습니다. 여기에는 더 많은 CPU를 사용하는 데 도움이되는 많은 옵션이 있습니다.

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