무작위 쓰레기를 생성하고 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
? 파이프는 리디렉션과 매우 다른가요? 결국 둘 다 pv
as 로 이동합니다 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
커널 소유 메모리를 통과하지 않도록 파이프에서 데이터를 복사합니다.