write vs fwrite. Что быстрее?
Модератор: Bizdelnick
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
write vs fwrite. Что быстрее?
Возникла задача записи в файл UDP пакетов, принимаемых от измерительного устройства. И время критично.
Из книги "Системное программирование в UNIX" узнал, что fwrite работает через write. Поэтому, по идее, write должен быть быстрее.
Но от разных людей слышал, что fwrite (почему-то) быстрее.
Кому верить?
Из книги "Системное программирование в UNIX" узнал, что fwrite работает через write. Поэтому, по идее, write должен быть быстрее.
Но от разных людей слышал, что fwrite (почему-то) быстрее.
Кому верить?
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Спасибо. Как я понимаю, fwrite имеет перед write преимущество в скорости записи только в случае записи фрагментов небольшой длины. И если после fwrite не используется fflush. И не будет иметь преимуществ при записи на твёрдотельные "диски", типа flash-накопителей.
P.S. 3-го издания книги Стивенса я в свободном доступе пока не нашёл. Нашёл 2-е издание, в формате DJVU
Сильно ли отличается 3-е издание от 2-го?
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
3-е издание дописано Раго через 15 лет после смерти Стивенса. Дополнено только самыми новыми API POSIX, всё остальное оставлено неизменным слово в слово, как мемориальное издание. 2-го издания вам хватит на многие годы вперёд.
-
NickLion
- Сообщения: 3408
- Статус: аватар-невидимка
- ОС: openSUSE Tumbleweed x86_64
Re: write vs fwrite. Что быстрее?
Что понимается под скоростью? MB/s? Низкие задержки? Можно писать в буфер вместо write, а в другом потоке параллельно записывать большими кусками. Или использовать mmap.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
От измерительного устройства поступает за секунду по сети около 2 тыс. пакетов. Размер одного пакета около 1500 байтов. Но также поступают пакеты и другого размера (десятки и сотни байтов). После получения пакета идёт обработка содержащихся в нём данных.
Для обеспечения последующего анализа возникла желание записывать принимаемые пакеты в файл. И, желательно, как можно быстрее, чтобы не пропускать принимаемые пакеты (приём по UDP)
Сейчас думаю, как организовать кольцевой буфер.То есть, чтобы было что-то вроде регистратора событий.
-
Bizdelnick
- Модератор
- Сообщения: 21432
- Статус: nulla salus bello
- ОС: Debian GNU/Linux
Re: write vs fwrite. Что быстрее?
У Вас пропускаются пакеты, или Вы предполагаете, что они могут пропускаться?
Пишите правильно:
| в консоли вку́пе (с чем-либо) в общем вообще | в течение (часа) новичок нюанс по умолчанию | приемлемо проблема пробовать трафик |
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Bizdelnick писал(а): ↑30.05.2016 14:20У Вас пропускаются пакеты, или Вы предполагаете, что они могут пропускаться?
У меня нет выбора. Хотелось бы, чтобы пакеты не пропускались. Но, так как поток поступающих данных довольно большой, да ещё и ресурсы ограничены (CPU 1.8 GHz, 2 ядра. или даже одно, системный диск может быть всего 4 ГБ). То хотелось бы минимизировать пропуск пакетов.
-
Bizdelnick
- Модератор
- Сообщения: 21432
- Статус: nulla salus bello
- ОС: Debian GNU/Linux
Re: write vs fwrite. Что быстрее?
MiK13
Вы не ответили на мой вопрос. У Вас есть реализация, которую Вы протестировали и обнаружили пропуск пакетов?
Вы не ответили на мой вопрос. У Вас есть реализация, которую Вы протестировали и обнаружили пропуск пакетов?
Пишите правильно:
| в консоли вку́пе (с чем-либо) в общем вообще | в течение (часа) новичок нюанс по умолчанию | приемлемо проблема пробовать трафик |
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
А вы не забыли, что протокол UDP - без гарантированной доставки, и согласно RFC (а это конечные стандарты для сети), сетевой стек сети IP Linux (и вообще любой ОС) имеет право при перегрузке просто сбрасывать приходящие UDP-пакеты в мусор, без всякого о том уведомлении - это не считается ошибка, это нормальное поведение IP-стека. И это будет всегда, независимо от того, делаете ли вы буферизацию или нет, и как вы это делаете.
Т.е. не потеря или искажение IP пакета в физической среде передачи - при этом как-раз на физическом уровне он будет повторён. Но из нормаьно полученного IP пакета выделена нормальная (в смысле целостности) UDP дэйтаграмма, но по соображениям перегрузки он на транспортном уровне (UDP/TCP) будет просто отброшен в мусор. То же при отправке: UDP дэйтаграммы могут просто даже не отправляться.
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
У вас действительно нет выбора
Протокол UDP в принципе придуман для другого ... главным образом: уведомлять при случае, или время от времени, о некоторых происходящих событиях ... и если уведомляемый пропустит уведомление, то и Бог с ним, возможно услышит при следующем уведомлении.
Это обычная и повсеместная ошибка, повторяющаяся тут и там из-за плохого понимания основ IP сети.
Есть 2 воспризводимых из разу в раз ошибки IP сетевого программирования ... как наступание на грабли: 1). надежда что "у меня" будет надёжная передача по UDP и 2). намерение передавать какие-то собственные пакеты, сообщения по TCP.
Спасибо сказали:
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Так что тут вам нужно не мучиться с буферизацией ... а вам снова приходит на помощь Стивенс:

Или более позднее переиздание:

Книги доступны, можете легко найти и скачать.

Или более позднее переиздание:

Книги доступны, можете легко найти и скачать.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Конечно есть.Bizdelnick писал(а): ↑30.05.2016 14:47MiK13
Вы не ответили на мой вопрос. У Вас есть реализация, которую Вы протестировали и обнаружили пропуск пакетов?
В передаваемых пакетах есть поле, номер которого непрерывно возрастает (в пределах 16 бит). Поэтому я могу замечать пропуск пакетов. И он иногда случается. Даже без протоколирования (хотя и реже).
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Это вам ничего не даёт.
Я это видел не один десяток раз в самоделках - всё те же грабли: вы пытаетесь реализовывать примитивный TCP над UDP ... потом вам этого станет мало - станете добавлять повтор потеряных дэйтаграм ... а для этого понадобится сообщать о потерянных обратно - и пошло и поехало.
Святая вера в то, что "на коленке" по UDP надёжная передача "у меня получится".
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Я это всё понимаю. И опыт пока показывает, что передача по UDP надёжнее, чем по TCP.Olej писал(а): ↑30.05.2016 14:56А вы не забыли, что протокол UDP - без гарантированной доставки, и согласно RFC (а это конечные стандарты для сети), сетевой стек сети IP Linux (и вообще любой ОС) имеет право при перегрузке просто сбрасывать приходящие UDP-пакеты в мусор, без всякого о том уведомлении - это не считается ошибка, это нормальное поведение IP-стека. И это будет всегда, независимо от того, делаете ли вы буферизацию или нет, и как вы это делаете.
Т.е. не потеря или искажение IP пакета в физической среде передачи - при этом как-раз на физическом уровне он будет повторён. Но из нормаьно полученного IP пакета выделена нормальная (в смысле целостности) UDP дэйтаграмма, но по соображениям перегрузки он на транспортном уровне (UDP/TCP) будет просто отброшен в мусор.
Как я понимаю, по TCP на каждый отправленный пакет приходит подтверждение, что он доставлен. А это -- дополнительная нагрузка на сеть. Да и на процессор, который и так не слабо загружен. Кроме того, пакеты, отправляемые одним устройством, могут принимать несколько устройств.И наоборот -- принимаемые пакеты могут приходить от нескольких устройств.
С SCTP я пока не разбирался. Может быть когда-нибудь займусь.
Что касается потери пакетов, то, как я понимаю, они могут возникать, если пакет пришёл, но я не успел выдать recvfrom ДО того момента, как пришёл следующий пакет. Поэтому решил, что лучше пусть я пропущу пакет, чем буду возиться с проверкой, из-за которой могу больше пропустить. Сеть локальная, никаких маршрутизаторов нет.
А по какой причинен они могут быть неотправленными?
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Как раз даёт информацию о том теряются пакеты или нет.
Повтор потерянных дэйтаграмм я добавлять не стану. По той причине, что в этом нет никакого смысла. Всё равно, что повторно передать информацию текущем времени. Которое уже стало другим.Olej писал(а): ↑30.05.2016 16:01Я это видел не один десяток раз в самоделках - всё те же грабли: вы пытаетесь реализовывать примитивный TCP над UDP ... потом вам этого станет мало - станете добавлять повтор потеряных дэйтаграм ... а для этого понадобится сообщать о потерянных обратно - и пошло и поехало.
Для меня главное -- минимизировать потерю пакетов.
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Опыт такого показывать не может. Такое может показать только глупость или самонадеяннсть: весь мир знает, что передача TCP надёжная, а UDP ненадёжная ... а тут пришёл орёл и все наработки 40 лет взял и порушил.
Широковещание в TCP организовать нельзя.
Приём с разных направлений - элементарно: откройте по сокету в каждом потоке.
Вы неправильно понимаете
Сетевой стек имеет право сбрасывать UDP дэйтаграммы до и вообще независимо от ваших recvfrom и вообще любых ваших действий.
По той же причине: сетевой стек перегружен и сброшено в мусор (кода ошибки вы не получите никаким способом).
P.S. Аккуратно используйте термин "пакет" применительно к UDP: пакет - это IP или Ethernet, дэйтаграмма UDP совсем не обязательно должна совпадать с пакетом канального или физического уровня.
У вас это не получится
(вы не контролируете ситуацию на 100%, это делает операционная система)
Вам лучше смириться с фактом и учитывать, что часть ваших UDP пакетов (непредсказуемо: 0.1%, 1%, 3%... будут бесследно терятся ... в зависимости от загрузки вашей LAN, например), но изменить архитектуру проекта так, чтобы эти непредсказуемые потери не сбивали его работу.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Есть поговорка: "лучше один раз увидеть, чем сто раз услышать".
По нажатию клавиши отправляется пакет другому устройству. Оно должно на него как-то отреагировать. И эта реакция видна на экране.
Я не раз видел, как устройство НЕ РЕАГИРОВАЛО на нажатие клавиши.
Например, по какой-то причине разрывался канал TCP. Как я понимаю, при этом send просто возвращает код ошибки. А значит надо его обработать, заново переоткрыть канал и послать сообщение ещё раз. Да ещё и следить за тем, чтобы не было зацикливания (например, из-за того, что кто-то вытащил сетевой кабель).
Я для приёма UDP-дейтаграмм по разным портам предпочёл использовать poll.
С этим согласен.
Я это понимаю. Поэтому моим основным вопросом был как минимизировать время записи данных в файл. Видимо, потом вообще сделаю кольцевой буфер в памяти и буду в него принимать дейтаграммы. А потом по сигналу записывать их в файл. Правда, остаётся вопрос как найти в этом буфере первую "неиспорченную" запись.Так, как дейтаграммы могут быть разной длины.
А мне ничего другого и не остаётся :-)
Только у нас, скорее, проблема не а загрузке LAN (100 МБит, по идее, должно хватать с запасом, а интенсивно передающее устройство одно), а в загрузке CPU.
Это само собой. Стараться сделать так, чтобы система работала.
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
MiK13 писал(а): ↑30.05.2016 17:21Есть поговорка: "лучше один раз увидеть, чем сто раз услышать".
По нажатию клавиши отправляется пакет другому устройству. Оно должно на него как-то отреагировать. И эта реакция видна на экране.
Я не раз видел, как устройство НЕ РЕАГИРОВАЛО на нажатие клавиши.
Например, по какой-то причине разрывался канал TCP. Как я понимаю, при этом send просто возвращает код ошибки. А значит надо его обработать, заново переоткрыть канал и послать сообщение ещё раз. Да ещё и следить за тем, чтобы не было зацикливания (например, из-за того, что кто-то вытащил сетевой кабель).
Это настолько
Книжки нужно читать, а не "видеть" (вот те, Стивенса, что я выше нарисовал).
Если в программах что-то "НЕ РЕАГИРОВАЛО" - то читай: говнокод
Если вы на общеизвестные вещи начинаете рассказывать ... : я не раз видел, что в моих условиях 2 х 2 даёт 5 - то от этого оно так не станет ... в ваших условиях.
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Вообще то, в IP стеке Linux уже есть кольцевой буфер принимаемых сокетных буферов (skbuf), в ядре...
Над ним надстроим 2-й кольцевой буфер...
Над ним надстроим 3-й кольцевой буфер...
...
Пирамида Хеопса.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
В книжках написана теория. А она часто заметно отличается от практики. В которой появляются дополнительные составляющие.
TCP в принципе не может гарантировать доставку информации, если другое устройство, вдруг, отключится. Или кто-то сетевой кабель разорвёт.
А такое в реальных условиях вполне может быть.
А есть в линуксе возможность хранить в файле последднюю сотню тысяч записей из принятых нескольких десятков миллионов?
Хотя, как я слышал, протоколировать принимаемые пакеты можно с помощью программы tcpdump. Но я пока не разобрался как это делать, и как их потом проигрывать. Причём, с возможностью управления: остановить, откатиться назад, продолжить с определённого места.
-
Bizdelnick
- Модератор
- Сообщения: 21432
- Статус: nulla salus bello
- ОС: Debian GNU/Linux
Re: write vs fwrite. Что быстрее?
Пишите правильно:
| в консоли вку́пе (с чем-либо) в общем вообще | в течение (часа) новичок нюанс по умолчанию | приемлемо проблема пробовать трафик |
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
В сетевом (сокетном) программировании, в отличие от всех других областей программирования, интерпретировать наблюдаемые эффекты непросто, с этим не следует спешить, происходящие там проявления очень часто радикально отличаются от того, что происходит на самом деле ("под крышкой").
Это часто связано с тем, что результат наших действий (в рограммном коде, например) проявляются с очень большой задержкой, иногда это секунды, а временами даже минуты... (это из-за того, что в IP сети работают много дополнительных механизмов, не сильно известные ... такие как алгоритм Нэйгла, отсроченное подтверждение, полу-закрытое соединение и всякие другие).
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Это ерунда.
По крайней мере в отношении IP - 100% ерунда.
А у вас есть в заначке протоколы, обеспечивающие доставку информации по разорванному сетевому кабелю?
"Пикантно ... пикантно" © поручик Ржевский.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Спасибо. Буду разбираться.
P.S. Выдал aptitude search rrd -- оказалось, что этот пакет входит в Debian. Поставил, буду изучать.
-
MiK13
- Сообщения: 1289
- ОС: Linux Debian
Re: write vs fwrite. Что быстрее?
Пока нет
Есть популярная реклама: "Если нет разницы, зачем платить больше?"
Как я понимаю:
Вариант TCP (тот, что сейчас)
При запуске программы инициализируется канал связи.
При нажатии клавиши в функции передачи выдаётся запрос send. (так было в первой версии, которую делал я, сейчас ей занимается другой человек, и там не send, а что-то аналогичное из Qt, но, думаю, в итоге тот же send)
Проверяется не было ли ошибки. Если была ошибка, канал закрывается и открывается заново.
Оператор, видя, что нет реакции, нажимает клавишу ещё раз. Всё срабатывает.
Если после нескольких раз не срабатывает, видимо, на принимающем устройстве что-то случилось. Приходится на нём нажимать кнопку "Сброс".
Хорошо, что оно презапускается за 2-3 секунды.
Кстати, программа на принимающем устройстве тоже не простая, так как должна слушать три TCP соединения, по трём портам.
При нажатии клавиши в функции передачи выдаётся запрос send. (так было в первой версии, которую делал я, сейчас ей занимается другой человек, и там не send, а что-то аналогичное из Qt, но, думаю, в итоге тот же send)
Проверяется не было ли ошибки. Если была ошибка, канал закрывается и открывается заново.
Оператор, видя, что нет реакции, нажимает клавишу ещё раз. Всё срабатывает.
Если после нескольких раз не срабатывает, видимо, на принимающем устройстве что-то случилось. Приходится на нём нажимать кнопку "Сброс".
Хорошо, что оно презапускается за 2-3 секунды.
Кстати, программа на принимающем устройстве тоже не простая, так как должна слушать три TCP соединения, по трём портам.
Думаю, что вариант UDP мог бы быть гораздо проще.
Открывается сокет для передачи UDP дейтаграмм.
По нажатию клавиши выдаётся sendto
Если нет реакции, оператор просто нажмёт ещё раз. Если после нескольких нажатий реакции не будет, значит что-то серьёзное.
И на приёмном конце, думаю, кусок приёма будет гораздо проще.
По нажатию клавиши выдаётся sendto
Если нет реакции, оператор просто нажмёт ещё раз. Если после нескольких нажатий реакции не будет, значит что-то серьёзное.
И на приёмном конце, думаю, кусок приёма будет гораздо проще.
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Это обычная логика всех начинающих знакомиться с IP и сокетным программированием (даже обсуждать не хочется, десятки раз уже в разных источниках обсуждено).
Читайте матчасть.
Правило такое, запоминайте
1. если нужна передача информации, в которой нельзя терять фрагменты, которая критична по времени доставки, которую нельзя многократно повторять (HTTP, FTP, SSH, SIP, ...) - используем только TCP;
2. если нужно уведомление о каких-то событиях (SNMP) или информацию можно повторно повторять несколько раз и время получения некритично (DNS) - используем UDP;
3. для передачи потока информации UDP используем только в очень специальных случаях, например, когда физический канал имеет затухания (радиоканал, радиоэзернет, ...)
-
Bizdelnick
- Модератор
- Сообщения: 21432
- Статус: nulla salus bello
- ОС: Debian GNU/Linux
Re: write vs fwrite. Что быстрее?
MiK13 писал(а): ↑30.05.2016 19:10Вариант TCP (тот, что сейчас)
При запуске программы инициализируется канал связи.
При нажатии клавиши в функции передачи выдаётся запрос send. (так было в первой версии, которую делал я, сейчас ей занимается другой человек, и там не send, а что-то аналогичное из Qt, но, думаю, в итоге тот же send)
Проверяется не было ли ошибки. Если была ошибка, канал закрывается и открывается заново.
Оператор, видя, что нет реакции, нажимает клавишу ещё раз. Всё срабатывает.
Если после нескольких раз не срабатывает, видимо, на принимающем устройстве что-то случилось. Приходится на нём нажимать кнопку "Сброс".
Хорошо, что оно презапускается за 2-3 секунды.
Кстати, программа на принимающем устройстве тоже не простая, так как должна слушать три TCP соединения, по трём портам.
Всё совершенно не так. Если рассматривать вариант с кнопкой и потерянным пакетом, последовательность будет такая:
- Устанавливается соединение.
- При нажатии кнопки, допустим, отправляется один пакет, который теряется.
- Дальше происходит одно из двух:
- Оператор нажимает кнопку ещё раз.
- Следующий пакет доходит до получателя, который по его номеру понимает, что предыдущий пакет был потерян.
- Получатель отправляет обратно ACK с номером пакета, предшествовавшего потерянному.
- Отправитель повторяет передачу двух пакетов.
- Получатель отправляет ACK с номером последнего полученного пакета.
- На принимающей стороне информация о двух нажатиях кнопки.
- Оператор ничего не делает.
- Не дождавшись подтверждения, отправляющая сторона посылает пакет повторно.
- Если пакет доходит, принимающая сторона отправляет ACK.
- На принимающей стороне информация об одном нажатии кнопки.
Главное: Вам и Вашему коду об этом беспокоиться не надо, это забота сетевого стека.
Пишите правильно:
| в консоли вку́пе (с чем-либо) в общем вообще | в течение (часа) новичок нюанс по умолчанию | приемлемо проблема пробовать трафик |
Спасибо сказали:
-
NickLion
- Сообщения: 3408
- Статус: аватар-невидимка
- ОС: openSUSE Tumbleweed x86_64
Re: write vs fwrite. Что быстрее?
Кстати, не заметил в обсуждении, прошу прощения, если проглядел, что UDP не гарантирует как доставку, так и порядок доставки. Т.е. если отправлены датаграммы
1, 2, 3, 4, 5, 6
то прийти могут
3, 1, 5, 6.
1, 2, 3, 4, 5, 6
то прийти могут
3, 1, 5, 6.
Спасибо сказали:
-
Olej
- Сообщения: 659
- ОС: Fedora, Mint, Debian, QNX
Re: write vs fwrite. Что быстрее?
Абсолютно верно.
Правда это относится только к WAN, но не к LAN.
Т.е. точнее так: это в теории так, но никогда не наблюдается в LAN, но легко наблюдается в WAN.
