파이프 및 리디렉션 속도, "pv" 및 UUOC

파이프 및 리디렉션 속도, "pv" 및 UUOC

무작위 쓰레기를 생성하고 pv다음과 같이 출력을 파이핑하여 속도를 비교하는 다양한 방법을 테스트하고 있습니다.

$ cmd | pv -s "$size" -S > /dev/null

나는 또한 "기준 참조"를 원했기 때문에 cat가장 빠른 소스로 가장 빠른 "생성기"를 측정했습니다 /dev/zero.

$ cat /dev/zero | pv -s 100G -S > /dev/null
 100GiB 0:00:33 [2,98GiB/s] [=============================>] 100%   

3GB/초, 특히 다음과 같은 경우 매우 인상적입니다.~70MB나는 에서 왔습니다 /dev/urandom.

/dev/zero하지만 특별한 경우에는 필요하지 않습니다 cat! 그냥 재미삼아 이 교과서를 지웠어요우루무치대학교:

$ < /dev/zero pv -s 100G -S > /dev/null
 100GiB 0:00:10 [9,98GiB/s] [=============================>] 100%            

무엇? ? ? 거의10GB/초? 철거 cat와 파이프라인은 어떻게 비교되나요?세 번속도? 예를 들어 느린 소스를 사용하는 경우 /dev/urandom차이는 무시할 수 있습니다. 마법을 부리는 걸까요 pv? 그래서 테스트했습니다:

$ dd if=/dev/zero iflag=count_bytes count=200G of=/dev/null status=progress
205392969728 bytes (205 GB, 191 GiB) copied, 16 s, 12,8 GB/s

12.8GB/초! 파이프를 사용하는 것과 거의 동일하며 pv, 파이프를 사용하는 것보다 4배 빠릅니다.

당신 자신의 잘못 인가요 cat? 파이프는 리디렉션과 매우 다른가요? 결국 둘 다 pvas 로 이동합니다 stdin. 그렇죠? 이 엄청난 차이를 무엇으로 설명할 수 있을까요?

답변1

비결은 두 가지 프로세스를 사용하는 것입니다.

동일 cat | pv, cat읽기 및 쓰기, pv읽기 및 쓰기, 두 프로세스가 모두 실행되어야 합니다.

$ perf stat sh -c 'cat /dev/zero | pv -s 100G -S > /dev/null'
 100GiB 0:00:26 [3.72GiB/s] [====================================================================================>] 100%            

 Performance counter stats for 'sh -c cat /dev/zero | pv -s 100G -S > /dev/null':

         34,048.63 msec task-clock                #    1.267 CPUs utilized          
         1,676,706      context-switches          #    0.049 M/sec                  
             3,678      cpu-migrations            #    0.108 K/sec                  
               304      page-faults               #    0.009 K/sec                  
   119,270,941,758      cycles                    #    3.503 GHz                      (74.89%)
   137,822,862,590      instructions              #    1.16  insn per cycle           (74.94%)
    32,379,369,104      branches                  #  950.974 M/sec                    (75.14%)
       216,658,446      branch-misses             #    0.67% of all branches          (75.04%)

      26.865741948 seconds time elapsed

       1.257950000 seconds user
      38.893870000 seconds sys

전용 pv, pv읽기 및 쓰기만 가능, 컨텍스트 전환이 필요하지 않음(또는 거의 없음):

$ perf stat sh -c '< /dev/zero pv -s 100G -S > /dev/null'
 100GiB 0:00:07 [13.3GiB/s] [====================================================================================>] 100%            

 Performance counter stats for 'sh -c < /dev/zero pv -s 100G -S > /dev/null':

          7,501.68 msec task-clock                #    1.000 CPUs utilized          
                37      context-switches          #    0.005 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
               198      page-faults               #    0.026 K/sec                  
    27,916,420,023      cycles                    #    3.721 GHz                      (75.00%)
    62,787,377,126      instructions              #    2.25  insn per cycle           (74.99%)
    15,361,951,954      branches                  # 2047.801 M/sec                    (75.03%)
        51,741,595      branch-misses             #    0.34% of all branches          (74.98%)

       7.505304560 seconds time elapsed

       1.768600000 seconds user
       5.733786000 seconds sys

일부 병렬 처리("1.267 CPU 사용")가 있지만 컨텍스트 전환 수의 큰 차이를 보상하지는 않습니다.

데이터 경로를 고려하면 상황은 아마도 훨씬 더 나쁠 것입니다. 첫 번째 경우 데이터는 /dev/zero커널( )에서 cat다시 커널(파이프의 경우)로, 그런 다음 pv커널( /dev/null)로 흐르는 것처럼 보입니다. 두 번째 경우에는 데이터가 코어에서 코어로 흐르고 pv다시 코어로 흐릅니다. 그러나 pv첫 번째 경우에는splice커널 소유 메모리를 통과하지 않도록 파이프에서 데이터를 복사합니다.

관련 정보