отправить полное содержимое кольцевого буфера при подписке, а затем отправить новые данные

Я новичок в boost::asio.

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

Другая часть модуля ожидает, пока потребитель откроет новое TCP-соединение или сокет домена unix, и когда соединение установлено, он отправляет полное содержимое кольцевого буфера, а затем отправляет любые новые данные, как только они помещаются в кольцевой буфер. . Разрешено несколько потребителей, и один потребитель может открыть новое соединение в любое время.

Первая наивная реализация, о которой я подумал, состоит в том, чтобы хранить отдельный asio::streambuf для каждого соединения и помещать в него весь кольцевой буфер при соединении, а затем каждые новые данные, но это кажется очень неоптимальным методом делать это как в памяти и циклы процессора, поскольку данные должны быть скопированы для каждого соединения, возможно, несколько раз, поскольку я не знаю, делает ли boost::asio::send (или стек linux tcp/ip) копию данных.

Поскольку моя идея состоит в том, чтобы вообще не использовать многопоточность, я думаю об использовании некоторой формы пользовательского производного класса asio::streambuf, который разделяет фактический буфер с кольцевым буфером, но сохраняет отдельное состояние указателя чтения без необходимости любого замка.

Мне кажется, это довольно необычная потребность, потому что я не могу найти какую-либо связанную документацию/вопрос, касающийся аналогичной темы, а документация по повышению кажется мне довольно краткой и скудной (см., например: http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/basic_streambuf.html).

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


person Patxitron    schedule 08.02.2015    source источник
comment
Документация по ускорению кажется мне довольно грубой и скудной Я собираюсь предположить грубую означает не то, что вы думали. Можете ли вы дать ссылку на документацию, которую вы не понимаете?   -  person sehe    schedule 08.02.2015
comment
Я видел два минуса. Я отредактировал вопрос, чтобы добавить тег linux, а затем я увидел один отрицательный голос, тогда я подумал, что это потому, что я оставил пустым краткое объяснение редактирования, поэтому я снова отредактировал только для того, чтобы оправдать предыдущее редактирование, и я я видел второй отрицательный голос. Я не знаю, получаю ли я автоматический отрицательный голос за каждое редактирование, или есть люди, отрицающие его, не объясняя свои причины.   -  person Patxitron    schedule 08.02.2015
comment
Это последнее. Ваш вопрос очень широк и не требует особых усилий. Я имею в виду именно то, что я сказал. Вы не показываете /что/ это доставляет вам неприятности. Вы не можете ожидать, что мы придумаем рабочий пример, но без конкретного кода, с которым вы застряли, вопрос не кажется подходящим для SO. (кстати, я в процессе написания ответа)   -  person sehe    schedule 08.02.2015
comment
Некоторые из ваших отрицательных голосов могут быть связаны с тем, что вы вообще не публиковали фрагмент кода о своих попытках. грубый -> рудиментарный также может улучшить принятие вопросов ;) Кроме того, многим может быть непонятно, почему вы просто не читаете из своей трубы и не обслуживаете обе свои конечные точки из 1 функции. Но, может быть, это из-за того, что я действительно не знаю о boost: asio. Если вы хотите что-то оптимизировать, сделайте это сами (вместо использования библиотеки) ;)   -  person BitTickler    schedule 08.02.2015
comment
@sehe: Извините, если я неправильно использую грубое слово. Я не англоговорящий человек, и в испанском rudo может быть более мягким термином. Я имею в виду boost.org/doc /libs/1_57_0/doc/html/boost_asio/reference/, и я хочу сказать, что это кажется мне недружественным для новичков, поскольку оно кажется очень кратким и объясняет, как его использовать, но я не могу понять, как из него извлечь пользовательский класс.   -  person Patxitron    schedule 08.02.2015
comment
@Patxitron Вы всегда можете обратиться к множеству примеров: boost .org/doc/libs/1_57_0/doc/html/boost_asio/examples.html   -  person sehe    schedule 08.02.2015
comment
@user2225104 user2225104 Я не могу опубликовать какой-либо фрагмент кода, потому что мой вопрос больше связан с дизайном. Вы правы, это довольно широкий вопрос, но я даже не могу получить какой-либо полезный параметр поиска, чтобы сузить его.   -  person Patxitron    schedule 08.02.2015
comment
Чего я до сих пор не вижу в вашем вопросе, так это того, когда вы в конечном итоге отказываетесь от информации, которую вы читали из своей трубы до сих пор. Когда подключается первый потребитель, или вы хотите сохранить свою информацию с самого начала, чтобы приходили все новые потребители?   -  person BitTickler    schedule 08.02.2015
comment
@user2225104 user2225104 Мое намерение состоит в том, что кольцевой буфер хранит последние N байтов, полученных из канала. Новые полученные байты перезаписывают самые старые. Затем, когда потребитель подключается, эти N самых новых байтов отправляются ему, а затем каждый новый полученный байт, как только он получен. Таким образом, потребитель не сбрасывает данные из кольцевого буфера, а его полное содержимое (история с ограниченным размером) доступно для новых потребителей.   -  person Patxitron    schedule 08.02.2015
comment
Если вы хотите что-то оптимизировать, сделайте это сами (вместо использования библиотеки) ;) - @user2225104 Для меня это звучит несколько перевернуто. Это больше похоже на синдром NIH или потенциально плохой выбор библиотеки. Я почти уверен, что баланс не меняется с библиотеками Boost. Они могут быть /больше, чем вам нужно/, но они редко ограничивают в каком-либо отношении.   -  person sehe    schedule 08.02.2015
comment
@sehe Все зависит от того, достаточно ли проста проблема, чтобы ее можно было решить, или она выходит за рамки того, что можно сделать. Я бы предпочел использовать некоторые оптимизированные математические алгоритмы из библиотеки. Но для написания очереди я бы предпочел этого не делать (здесь std::queue не считается библиотекой). Ни для открытия сокета, ни для чтения из канала. Нет, если бы мне пришлось потратить больше времени на изучение библиотеки, чем мне понадобилось бы, чтобы написать ее самому.   -  person BitTickler    schedule 08.02.2015
comment
@user2225104 user2225104 дело в том, что типичная библиотека boost должна быть чрезвычайно сложной, чтобы она больше не могла идти в ногу со временем. Но я не буду спорить о вкусе, потому что это карта, которую вы на самом деле тянете.   -  person sehe    schedule 08.02.2015


Ответы (2)


Вы должны просто делать то, что намереваетесь.

Вам абсолютно не нужен streambuf для использования с Boost Asio: http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/buffer.html

Если проблема заключается в том, как избежать того, чтобы производитель «ждал», пока все потребители (читай: соединения) не закончат передачу данных, вы всегда можете использовать старый трюк с чередованием выходных буферов.

Многие реализации кольцевого буфера допускают прямое сращивание сразу полной последовательности элементов (например, ускорить доступ к кэш-памяти spsc_queue без блокировки). Вы можете использовать такую ​​операцию в своих интересах.

Также актуально:

person sehe    schedule 08.02.2015
comment
Добавлена ​​ссылка на дополнительные сведения (плюс полные идеи дизайна и ссылки на реализации/презентации) о нулевом копировании с использованием Boost Asio. - person sehe; 08.02.2015

Оказывается, речь здесь идет о производительности. Независимо от того, используется ли boost:: asio или какое-либо решение, связанное вручную, производительность (пропускная способность) может уже снижаться из-за того факта (как указано в разделе комментариев OP), что торгуются отдельные байты (читайте из канал).
После начальной «фазы взрыва», когда потребитель подключается, отдельные байты просачиваются из канала в подключенные сокеты потребителя с операциями чтения() и записи() на байт (или несколько байтов, если приложение не опрашивается постоянно).
Учитывая это (тот факт, что плата за системные вызовы read() и write() приходится на небольшие объемы данных), я осмелюсь предположить, что все, что связано с несколькими очередями или одной очередью и т. д., уже в тени этого основного «ошибки конструкции». Я беру «ошибку дизайна» в кавычки, так как не всегда можно избежать именно такой ситуации.

Итак, если пропускную способность все равно нельзя оптимизировать, я бы порекомендовал самое простое и понятное решение, какое только можно придумать.

Оператор «без потоков» в OP подразумевает неблокирующие файловые дескрипторы как для сокета приема, сокетов потребительских данных, так и для канала. Будет ли это еще одно приложение для опроса, на 100% потребляющее процессор/ядро? Если это не какая-то проблема гипероптимизации специальных операций, я бы не советовал использовать неблокирующие дескрипторы файлов. Кроме того, я бы не беспокоился о нулевой копии или нет.

Одним из простых подходов к потокам было бы неблокировать потребительские сокеты, в то время как канал находится в блокирующем режиме. Поток, который читает канал, затем загружает данные в очередь и вызывает функцию, которая обслуживает всех подключенных в данный момент потребителей. Сокет прослушивания (тот, который вызывает accept()) находится в сигнальном состоянии, когда ожидаются новые клиентские подключения. С такими механизмами, как kqueue (bsd) или epoll (linux и т. д.) или WaitForMultipleObjects (windows), поток чтения каналов также может реагировать на эту ситуацию.

В то время, когда ничего не нужно делать, ваше приложение спит/блокируется и дружественно к нашей среде :)

person BitTickler    schedule 08.02.2015
comment
Я предполагаю, что функциональность файлового дескриптора posix в boost::asio выполняет за меня функцию epoll без необходимости самостоятельно потреблять циклы процессора при активном опросе, как в boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/chat/ фактически Я уже экспериментировал с этой функцией: github.com/patxitron/BattleyeRconToolLinux - person Patxitron; 09.02.2015
comment
Вы правы, после загрузки буфера данные будут отправляться не точно побайтно, а по несколько байтов за раз (чаще всего менее 100 за раз). Теперь я думаю об отправке этих обновлений путем повторения массива зарегистрированных сокетов. Спасибо за помощь. - person Patxitron; 09.02.2015