เหตุใดไพพ์ที่มีชื่อจึงช้าเท่ากับการเขียนไฟล์?


18

ฉันพยายามที่จะเข้าใจว่าการตั้งชื่อไปป์นั้นทำงานอย่างไรเพื่อให้ฉันสามารถปรับปรุงการสื่อสารระหว่างทางแบบทางเดียวได้อย่างคล่องตัว ฉันคาดว่าค่าโสหุ้ยเนื่องจากการคัดลอกข้อมูลลงในบัฟเฟอร์แบบวงกลมซึ่งฉันคิดว่าจะถูกเก็บไว้ใน RAM และดังนั้นฉันจึงคาดว่าท่อจะเร็วกว่าการเขียนไปยังไฟล์มาก (เนื่องจาก RAM มีขนาดของคำสั่งเร็วกว่าดิสก์)

แต่ฉันพบว่าไปป์ที่มีชื่อ (หรือไปป์ที่ไม่ระบุชื่อ) มีความเร็วประมาณเดียวกับไฟล์ นี่เป็นเดสก์ท็อป 3 GHz ที่มีดิสก์ไดรฟ์ทั่วไป (ไม่ใช่โซลิดสเตต) ซึ่งใช้ Ubuntu Linux นี่คือโปรแกรมทดสอบที่เรียบง่ายใน Python:

import sys
import time
import random

megabyte = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for x in range(1024**2))

while True:
    before = time.time()
    sys.stdout.write(megabyte)
    after = time.time()
    sys.stderr.write("{} microseconds\n".format(1e6 * (after - before)))

ท่อตรงไปที่/dev/null:

python test.py > /dev/null

ให้ผลผลิต 2.1 microseconds (คงที่) สำหรับแต่ละเมกะไบต์

ไปป์ที่ไฟล์:

python test.py > /tmp/testout.txt

ข้ามไปมาระหว่าง 500 microseconds และ 930 microseconds (ค่าที่มากกว่านั้นจะได้รับความสามัญมากกว่าเมื่อไฟล์มีขนาดใหญ่ขึ้น - สมมุติว่ามันกำลังมองหาพื้นที่ดิสก์)

จากนั้นไปป์ที่มีชื่อ:

mkfifo testpipe
cat testpipe > /dev/null &
python test.py > testpipe

ให้ผลผลิต 640 microseconds (ค่าคงที่) และท่อที่ไม่มีชื่อ:

python test.py | cat > /dev/null

ยังให้ผลผลิต 650 microseconds (คงที่)

ใครสามารถอธิบายได้ว่าทำไมความเร็วของไพพ์จึงมากกว่าความเร็วของไฟล์มากกว่า/dev/null? ฉันอาจมีสวิตช์ที่บอกว่า "เรียกใช้ไพพ์ผ่านบัฟเฟอร์ที่อิงกับไฟล์มากกว่าบัฟเฟอร์ตามแรม" และฉันสามารถเปลี่ยนสวิตช์นั้นได้หรือไม่ มันอาจเป็นตัวเลือกเคอร์เนลหรือตัวแปรเชลล์?

การตีความอื่น: สมมติว่าเอาต์พุตของดิสก์กระโดดระหว่าง 500 และ 930 ไมโครวินาทีเนื่องจาก 500 เป็นเพียงการไพพ์และ 930 นั้นกำลังเขียนจริง จากนั้น 500 ~ 640 สำหรับการวางท่อในทั้งสองกรณีจะเทียบเท่ากัน อย่างไรก็ตามภายใต้การตีความนั้นเหตุใดจึงมีเพียงสองอย่างระหว่างการไพพ์และการเขียนลงดิสก์จริง ๆ เว็บไซต์ที่พูดถึงดิสก์ RAMบอกว่าดิสก์ RAM เร็วกว่าฮาร์ดดิสก์ 50-200 เท่า


1
/dev/nullจริงๆแล้วการเขียนไปนั้นค่อนข้างถูกในขณะที่เขียนที่อื่นไม่ว่าจะเป็นไฟล์, FIFO, ไพพ์หรืออะไรก็ตาม - มันแพงกว่ามากเพราะมันต้องใช้ความพยายามอย่างมากในการจัดการ
glglgl

คำตอบ:


31

คุณไม่เห็นประโยชน์ด้านประสิทธิภาพใด ๆ เพราะคุณไม่ได้กดปุ่มดิสก์เมื่อใช้ไฟล์ - ข้อมูลกำลังจะมาถึงดิสก์ แต่เธรดการเรียกใช้ของคุณไม่จำเป็นต้องรอให้ถึงจุดนั้น ไม่เห็นการลงโทษความเร็วในการกดปุ่มดิสก์

หากคุณต้องการรอให้การดำเนินการของดิสก์เสร็จสมบูรณ์เพื่อดูว่าช้าลงเท่าใดที่จะได้รับโปรดโทร a sync()(จะแตกต่างกันอย่างไรกับเวอร์ชั่นไพ ธ อนของคุณดูที่นี่ ) - คุณจะดูไมโครวินาทีนับหมื่นเพื่อให้ดิสก์ของคุณ หาสองสามครั้งเพื่อเขียนไฟล์ (สมมติว่ามันไม่มีแคชเขียนเร็วเหมือนในคอนโทรลเลอร์ RAID)


เมื่อไหร่ที่เราจะหยุดกังวลเกี่ยวกับเวลาค้นหาของอุปกรณ์บล็อกของเรา :)
EEAA

5
@EEAA SSD ทั้งหมดตลอดเวลา

1
คุณพูดถูก: ด้วยsync()เวลาเขียนดิสก์จะเฉลี่ย 74,000 ไมโครวินาที ( flush()ฉันทำการทดสอบในรูปแบบต่าง ๆ ไม่ได้ทำอย่างนั้น) ดังนั้นการตีความของฉันว่า 500 ~ 640 microseconds ต่อเมกะไบต์จริง ๆ แล้วเป็นค่าใช้จ่ายของท่อที่ทำให้รู้สึกขอบคุณ
Jim Pivarski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.