Tại sao echo> file sử dụng nhiều thời gian thực hơn echo | sed> tập tin?


28

Ví dụ, dưới đây, làm tôi ngạc nhiên. Nó dường như phản tác dụng trực quan ... ngoài thực tế là có nhiều thời gian hơn cho người dùng cho echo | sedcombo.

Tại sao echosử dụng quá nhiều thời gian sys khi nó chạy một mình, hoặc câu hỏi nên là, làm thế nào để sedthay đổi trạng thái chơi? Có vẻ như echosẽ cần phải thực hiện cùng một tiếng vang trong cả hai trường hợp ...

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
Phản ứng ruột của tôi là nó phải làm với bộ đệm.
bahamat

1
@bahamat Tôi nghĩ bạn đúng. Các echo làm một write () riêng cho mỗi đối số. Các sed đệm họ. Vì vậy, phiên bản đầu tiên có một triệu lần ghi vào một tệp thông thường, thông qua trình điều khiển hệ thống tệp vào lớp thiết bị khối và phiên bản thứ hai có một triệu lần ghi vào một đường ống và phần nào ghi ít hơn qua các lớp mã nhân đắt tiền hơn.
Alan Curry

@bahamat Chắc chắn là đệm. time echo ... |cat >filevà thậm chí time echo ... |perl -ne 'print'là thời gian tương tự như sedphiên bản.
StarNamer

4
Cảm ơn tất cả mọi người vì những lời giải thích tốt ... Vì vậy, đối với việc viết nhiều dòng lớn (trong bash), con mèo đã đạt được điểm Sử dụng hữu ích của điểm mèo :)
Peter.O

Câu trả lời:


29

bahamat và Alan Curry có quyền: điều này là do cách vỏ của bạn đệm đầu ra echo. Cụ thể, shell của bạn là bash và nó phát ra một writecuộc gọi hệ thống trên mỗi dòng. Do đó đoạn mã thứ nhất thực hiện ghi 1000000 vào tệp đĩa, trong khi đoạn mã thứ hai tạo 1000000 ghi vào đường ống và sed (phần lớn song song, nếu bạn có nhiều CPU) sẽ tạo ra số lượng ghi nhỏ hơn đáng kể vào tệp đĩa do đầu ra của nó đệm.

Bạn có thể quan sát những gì đang xảy ra bằng cách chạy 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) ---

Các shell khác như ksh đệm đầu ra echongay cả khi nó là multiline, vì vậy bạn sẽ không thấy nhiều sự khác biệt.

$ 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

Với bash tôi nhận được tỷ lệ thời gian tương tự. Với ksh tôi thấy đoạn mã thứ hai chạy chậm hơn.

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

Cảm ơn ... kshVí dụ cuối cùng này phù hợp hơn với những gì tôi mong đợi ...
Peter.O
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.