Tại sao một ống có tên chậm như ghi vào một tập tin?


18

Tôi đang cố gắng hiểu làm thế nào các đường ống được đặt tên hoạt động để tôi có thể hợp lý hóa giao tiếp một chiều của tôi. Tôi mong đợi một số chi phí do sao chép dữ liệu vào bộ đệm tròn, mà tôi nghĩ là được lưu trữ trong RAM, và vì vậy tôi hy vọng đường ống sẽ nhanh hơn nhiều so với ghi vào tệp (vì RAM là đơn đặt hàng có cường độ nhanh hơn đĩa).

Thay vào đó, tôi thấy rằng ống có tên (hoặc ống ẩn danh) có cùng tốc độ với một tệp. Đây là trên máy tính để bàn 3 GHz với ổ đĩa thông thường (không phải trạng thái rắn), chạy Ubuntu Linux. Đây là một chương trình thử nghiệm đơn giản hóa trong 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)))

Đường ống thẳng đến /dev/null:

python test.py > /dev/null

mang lại 2,1 micro giây (không đổi) cho mỗi megabyte.

Đường ống đến một tập tin:

python test.py > /tmp/testout.txt

nhảy giữa 500 micro giây và 930 micro giây (giá trị lớn hơn trở nên phổ biến hơn khi tệp trở nên lớn hơn --- có lẽ, nó đang tìm không gian đĩa).

Sau đó, ống được đặt tên:

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

mang lại 640 micro giây (không đổi) và một ống không tên:

python test.py | cat > /dev/null

cũng mang lại 650 micro giây (không đổi).

Bất cứ ai cũng có thể giải thích tại sao tốc độ của ống giống như tốc độ của tệp hơn /dev/nulllà tốc độ? Tôi có thể có một công tắc ở đâu đó có nội dung: "chạy các đường ống thông qua bộ đệm dựa trên tệp, thay vì bộ đệm dựa trên RAM" và tôi có thể thay đổi công tắc đó không? Nó có thể là một tùy chọn kernel hoặc một biến shell?

Một cách giải thích khác: giả sử rằng đầu ra đĩa nhảy trong khoảng 500 đến 930 micro giây vì 500 chỉ là đường ống và 930 thực sự đang ghi. Thì 500 ~ 640 cho đường ống trong cả hai trường hợp là tương đương. Tuy nhiên, theo cách giải thích đó, tại sao chỉ có một yếu tố hai giữa đường ống và thực sự ghi vào đĩa? Các trang web nói về đĩa RAM nói rằng đĩa RAM nhanh hơn 50-200 lần so với đĩa cứng.


1
Viết cho /dev/nullthực sự khá rẻ, trong khi viết ở bất cứ nơi nào khác - có thể là một tập tin, một bộ xếp hình, một ống hoặc bất cứ thứ gì - đắt hơn nhiều vì nó cần "rất nhiều" nỗ lực xử lý.
glglgl

Câu trả lời:


31

Bạn không thấy bất kỳ lợi ích hiệu suất nào vì bạn không thực sự nhấn đĩa khi sử dụng tệp - dữ liệu đang trên đường đến đĩa, nhưng luồng thực thi của bạn không cần phải đợi nó đến đó, vì vậy bạn không thực sự thấy hình phạt tốc độ của việc đánh đĩa.

Nếu bạn muốn đợi cho hoạt động của đĩa hoàn tất để xem tốc độ của nó chậm hơn bao nhiêu, hãy gọi một sync()(cách thay đổi trên phiên bản python của bạn, xem tại đây ) - bạn sẽ xem xét hàng chục nghìn micro giây chỉ cho đĩa của bạn tìm kiếm một vài lần để lấy tệp ra (giả sử nó không có bộ đệm ghi nhanh như trong bộ điều khiển RAID).


Khi nào chúng ta có thể ngừng lo lắng về thời gian tìm kiếm các thiết bị khối của mình? :)
EEAA

5
@EEAA Tất cả các ổ SSD, mọi lúc.

1
Bạn nói đúng: với sync()thời gian ghi đĩa trung bình trở thành 74.000 micro giây. ( flush()Tôi đã thực hiện một biến thể trong bài kiểm tra của mình đã không làm điều đó.) Vì vậy, cách giải thích của tôi rằng 500 ~ 640 micro giây trên mỗi megabyte thực sự là chi phí hợp lý, cảm ơn.
Jim Pivarski
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.