Почему именованный канал медленнее, чем запись в файл?

18

Я пытаюсь понять, как работают именованные каналы, чтобы упростить одностороннее межпроцессное взаимодействие. Я ожидаю некоторых издержек из-за копирования данных в кольцевой буфер, который, как я думал, хранится в ОЗУ, и поэтому я ожидал, что канал будет намного быстрее, чем запись в файл (потому что ОЗУ на несколько порядков быстрее, чем диск).

Вместо этого я обнаружил, что именованный канал (или анонимный канал) примерно с той же скоростью, что и файл. Это на рабочем столе 3 ГГц с обычным дисководом (не твердотельным), работающим под управлением 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 микросекунды (постоянные) для каждого мегабайта.

Трубопровод к файлу:

python test.py > /tmp/testout.txt

скачки между 500 микросекундами и 930 микросекундами (чем больше размер файла, тем больше значение становится более распространенным - предположительно, он ищет место на диске).

Тогда названная труба:

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

дает 640 микросекунд (постоянная) и безымянный канал:

python test.py | cat > /dev/null

также дает 650 микросекунд (постоянная).

Кто-нибудь может объяснить, почему скорость канала больше похожа на скорость файла, чем /dev/nullскорость? Может быть, у меня где-то есть переключатель, который говорит: «Пропустить каналы через файловый буфер, а не буфер ОЗУ», и могу ли я изменить этот переключатель? Это может быть опция ядра или переменная оболочки?

Другая интерпретация: предположим, что выходная мощность диска колеблется между 500 и 930 микросекундами, потому что 500 - это просто трубопровод, а 930 - фактически запись. Тогда 500 ~ 640 для трубопровода в обоих случаях эквивалентны. Тем не менее, согласно этой интерпретации, существует только два фактора между конвейером и записью на диск? Веб-сайты, которые говорят о RAM-дисках, говорят, что RAM-диски в 50-200 раз быстрее жестких дисков.

Джим Пиварски
источник
1
Запись на /dev/nullсамом деле довольно дешева, в то время как запись в любом другом месте - будь то файл, FIFO, канал или что-то еще - намного дороже, поскольку требует «больших» усилий по обработке.
glglgl

Ответы:

31

Вы не видите какого-либо выигрыша в производительности, потому что на самом деле вы не нажимаете на диск при использовании файла - данные находятся на пути к диску, но ваш поток выполнения не должен ждать, пока он попадет туда, поэтому вы на самом деле не вижу потери скорости удара диска.

Если вы хотите дождаться завершения операции с диском, чтобы увидеть, насколько медленнее это происходит, вызовите a sync()(как это зависит от вашей версии Python, см. Здесь ) - вы будете искать десятки тысяч микросекунд только для того, чтобы ваш диск мог ищите пару раз, чтобы записать файл (при условии, что у него нет какого-либо кеша быстрой записи, как в RAID-контроллере).

Шейн Мэдден
источник
Когда мы перестанем беспокоиться о времени поиска наших блочных устройств? :)
EEAA
5
@EEAA Все SSD, все время.
1
Вы правы: время записи sync()на диск в среднем составляет 74 000 микросекунд. (То, что flush()я делал в одном из вариантов моего теста, не делало этого.) Итак, моя интерпретация, что 500 ~ 640 микросекунд на мегабайт на самом деле являются издержками канала, имеет смысл, спасибо.
Джим Пиварски