Я пытаюсь понять, как работают именованные каналы, чтобы упростить одностороннее межпроцессное взаимодействие. Я ожидаю некоторых издержек из-за копирования данных в кольцевой буфер, который, как я думал, хранится в ОЗУ, и поэтому я ожидал, что канал будет намного быстрее, чем запись в файл (потому что ОЗУ на несколько порядков быстрее, чем диск).
Вместо этого я обнаружил, что именованный канал (или анонимный канал) примерно с той же скоростью, что и файл. Это на рабочем столе 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 раз быстрее жестких дисков.
/dev/null
самом деле довольно дешева, в то время как запись в любом другом месте - будь то файл, FIFO, канал или что-то еще - намного дороже, поскольку требует «больших» усилий по обработке.Ответы:
Вы не видите какого-либо выигрыша в производительности, потому что на самом деле вы не нажимаете на диск при использовании файла - данные находятся на пути к диску, но ваш поток выполнения не должен ждать, пока он попадет туда, поэтому вы на самом деле не вижу потери скорости удара диска.
Если вы хотите дождаться завершения операции с диском, чтобы увидеть, насколько медленнее это происходит, вызовите a
sync()
(как это зависит от вашей версии Python, см. Здесь ) - вы будете искать десятки тысяч микросекунд только для того, чтобы ваш диск мог ищите пару раз, чтобы записать файл (при условии, что у него нет какого-либо кеша быстрой записи, как в RAID-контроллере).источник
sync()
на диск в среднем составляет 74 000 микросекунд. (То, чтоflush()
я делал в одном из вариантов моего теста, не делало этого.) Итак, моя интерпретация, что 500 ~ 640 микросекунд на мегабайт на самом деле являются издержками канала, имеет смысл, спасибо.