เหตุใดไฟล์ echo> ใช้เวลาจริงมากกว่า echo | sed> file?


28

ตัวอย่างด้านล่างทำให้ฉันประหลาดใจ ดูเหมือนว่าจะตอบโต้ได้ง่าย ... นอกเหนือจากความจริงที่ว่ามีเวลาผู้ใช้มากขึ้นสำหรับecho | sedคอมโบ

เหตุใดจึงechoใช้เวลามากเมื่อทำงานเพียงอย่างเดียวหรือคำถามควรsedเปลี่ยนสถานะการเล่นอย่างไร ดูเหมือนว่าechoจะต้องทำเสียงสะท้อนที่เหมือนกันในทั้งสองกรณี ...

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 ฉันคิดว่าคุณพูดถูก เสียงก้องจะเขียนแยก () สำหรับแต่ละอาร์กิวเมนต์ รถบดบังพวกเขา ดังนั้นรุ่นแรกมีล้านเขียนไปยังไฟล์ปกติจะผ่านไดรเวอร์ระบบไฟล์ลงในเลเยอร์อุปกรณ์บล็อกและรุ่นที่สองมีล้านเขียนไปที่ไพพ์และเขียนน้อยกว่าจะผ่านเลเยอร์ราคาแพงกว่าของเคอร์เนลรหัส
Alan Curry

@bahamat กำลังบัฟเฟอร์แน่นอน time echo ... |cat >fileและแม้กระทั่งtime echo ... |perl -ne 'print'เวลาที่คล้ายกันกับsedรุ่น
StarNamer

4
ขอบคุณทุกคนสำหรับคำอธิบายที่ดี ... ดังนั้นสำหรับการเขียนหลายบรรทัดขนาดใหญ่ (ในทุบตี) แมวได้รับประโยชน์การใช้งานของจุด Cat :)
Peter.O

คำตอบ:


29

bahamat และอลันแกงมีมันขวา: echoนี้เป็นเพราะวิธีการที่เปลือกของคุณบัฟเฟอร์การส่งออกของ เชลล์ของคุณมีการทุบตีโดยเฉพาะและจะwriteเรียกการเรียกใช้ระบบหนึ่งรายการต่อบรรทัด ดังนั้นตัวอย่างแรกทำให้ 1000000 เขียนไปยังไฟล์ดิสก์ในขณะที่ตัวอย่างที่สองทำให้ 1000000 เขียนไปยังไปป์และ sed (ส่วนใหญ่ในแบบคู่ขนานถ้าคุณมี CPU หลายตัว) ทำให้เขียนจำนวนน้อยลงไปยังดิสก์ไฟล์เนื่องจากผลลัพธ์ บัฟเฟอร์

คุณสามารถสังเกตเห็นสิ่งที่เกิดขึ้นโดยการเรียกใช้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

เมื่อทุบตีฉันจะได้อัตราส่วนเวลาใกล้เคียงกัน ด้วย 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ตัวอย่างสุดท้ายนั้นเป็นไปตามสิ่งที่ฉันคาดไว้มากขึ้น ...
Peter.O
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.