echo> file이 echo보다 실시간을 더 많이 사용하는 이유 | sed> 파일?


28

아래의 예는 저를 놀라게했습니다. 수염 더 있다는 사실을 제외하고 ... 카운터 직관적 인 것 같다 사용자 시간 에 대한 echo | sed콤보.

단독으로 실행될 때 시스템 시간echo 을 너무 많이 사용하는 이유는 무엇입니까? 또는 게임 상태를 어떻게 변경합니까? 두 경우 모두 동일한 에코 를 수행해야 할 것 같습니다 ... sedecho

time echo -n a\ {1..1000000}\ c$'\n' >file

# real    0m9.481s
# user    0m5.304s
# sys     0m4.172s

time echo -n a\ {1..1000000}\ c$'\n' |sed s/^\ // >file

# real    0m5.955s
# user    0m5.488s
# sys     0m1.580s

1
내 직감은 버퍼링과 관련이 있습니다.
bahamat

1
@bahamat 당신이 옳다고 생각합니다. 에코는 각 인수에 대해 별도의 write ()를 수행합니다. sed는 그것들을 버퍼링합니다. 따라서 첫 번째 버전은 파일 시스템 드라이버를 통해 블록 장치 계층으로 들어가는 일반 파일에 백만 번 쓰고, 두 번째 버전은 파이프로 백만 번 쓰고 더 비싼 커널 코드 계층을 통한 쓰기는 줄어 듭니다.
Alan Curry

@bahamat 확실히 버퍼링. time echo ... |cat >file심지어 버전 time echo ... |perl -ne 'print'과 비슷한 시간 sed입니다.
StarNamer

4
좋은 설명을
해주신

답변:


29

bahamat와 Alan Curry는 옳습니다. 이것은 쉘이 출력을 버퍼링하는 방식 때문입니다 echo. 특히, 쉘은 bash이며 write라인 당 하나의 시스템 호출을 발행 합니다. 따라서 첫 번째 스 니펫은 디스크 파일에 1000000 쓰기를 작성하는 반면, 두 번째 스 니펫은 파이프에 1000000 쓰기를 작성하고 (여러 개의 CPU가있는 경우 거의 병렬로) sed는 출력으로 인해 디스크 파일에 대한 쓰기 수가 상당히 적습니다. 버퍼링.

strace 를 실행하여 진행 상황을 관찰 할 수 있습니다 .

$ strace -f -e write bash -c 'echo -n a\ {1..2}\ c$'\'\\n\'' >file'
write(1, "a 1 c\n", 6)                  = 6
write(1, " a 2 c\n", 7)                 = 7
$ strace -f -e write bash -c 'echo -n a\ {1..2}\ c$'\'\\n\'' | sed "s/^ //" >file'
Process 28052 attached
Process 28053 attached
Process 28051 suspended
[pid 28052] write(1, "a 1 c\n", 6)      = 6
[pid 28052] write(1, " a 2 c\n", 7)     = 7
Process 28051 resumed
Process 28052 detached
Process 28051 suspended
[pid 28053] write(1, "a 1 c\na 2 c\n", 12) = 12
Process 28051 resumed
Process 28053 detached
--- SIGCHLD (Child exited) @ 0 (0) ---

ksh와 같은 다른 쉘은 여러 줄 echo이라도 출력을 버퍼링 하므로 큰 차이는 없습니다.

$ strace -f -e write ksh -c 'echo -n a\ {1..2}\ c$'\'\\n\'' >file'
write(1, "a 1 c\n a 2 c\n", 13)         = 13
$ strace -f -e write ksh -c 'echo -n a\ {1..2}\ c$'\'\\n\'' | sed "s/^ //" >file'
Process 28058 attached
[pid 28058] write(1, "a 1 c\n a 2 c\n", 13) = 13
Process 28058 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
write(1, "a 1 c\na 2 c\n", 12)          = 12

bash를 사용하면 비슷한 타이밍 비율을 얻습니다. ksh를 사용하면 두 번째 스 니펫이 느리게 실행되는 것을 볼 수 있습니다.

ksh$ time echo -n a\ {1..1000000}\ c$'\n' >file

real    0m1.44s
user    0m1.28s
sys     0m0.06s
ksh$ time echo -n a\ {1..1000000}\ c$'\n' | sed "s/^ //" >file

real    0m2.38s
user    0m1.52s
sys     0m0.14s

고마워요 ... 마지막 ksh예는 제가 기대했던 것보다 더
낫습니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.