Использование protobuf для связи потоков - PullRequest
0 голосов
/ 24 июня 2019

Я знаю, что существует множество дискуссий о многопоточном обмене данными, но я не нашел ни одного, связанного с protobuf для общения.

Справочная информация: Недавно я написал приложение, в котором я использовал protobuf для связи между сокетами. Мое приложение порождает разные потоки, и эти потоки должны иметь возможность общаться друг с другом.

Это было сделано путем помещения объектов (экземпляров классов) в '' std :: queue ''. Итак, я в основном один поток создаю экземпляр класса с моей информацией, помещая его в «очередь», а другой мой поток извлекает объекты из этой очереди (или буфера) и обрабатывает их.

Теперь мне стало интересно, не лучше ли будет использовать «protobuf» для общения вместо созданных объектов. Основная идея заключалась в создании сообщения protobuf вместо целого экземпляра класса и помещении их в очередь. Таким образом, основная идея состояла в том, чтобы создать «очередь», которая содержит список двоичной строки, сгенерированной с использованием метода «protobuf» SerializeToString().

Может ли это быть более чистый (и более эффективный) способ обмена данными между потоками?

1 Ответ

1 голос
/ 02 июля 2019

Подводя итог: с помощью метода 1 вы ставите в очередь и удаляете объекты из очереди на std::queue.При использовании метода 2 вы все равно используете очередь, но сериализуете только необходимые части объекта в очередь.

В конце концов, звучит так, будто нет разницы в том, что касается потоков.Это все та же ситуация производителя / потребителя.Независимо от того, какой метод связи вы используете, код клиента не меняется.Ни один из способов не является «чище».

Способ 1 более эффективен.Потоки были придуманы для оптимизации, чтобы вы могли совместно использовать память.

Метод 1 создает объект один раз и уничтожает его один раз.Метод 2 создает объект дважды и уничтожает его дважды.Объект создается потоком производителя, который затем сериализует его и уничтожает объект.Объект повторно создается из десериализованных данных потоком потребителя, который использует его, а затем уничтожает.Даже если метод 2 может каким-то образом оптимизировать создание экземпляра объекта (например, используя массив char вместо объекта string), вы можете применить ту же оптимизацию к методу 1.

Метод 1 может просто прочитатьобъект, так как память является общей.Метод 2 должен скопировать информацию об объекте в буфер, а затем скопировать ее обратно.Это две дополнительные копии.

У метода 1 накладные расходы в очереди.Как правило, в очереди просто есть указатель на объект, поэтому постановка в очередь и снятие очереди обходятся дешево.Очередь может быть реализована через массив.У метода 2 также есть издержки очереди.Однако все данные хранятся в очереди, поэтому постановка в очередь и снятие очереди зависит от размера сериализованных данных.Даже если сериализованные данные невелики, это не быстрее, чем метод 1.

Метод 1 - многопоточность с общей памятью.Метод 2 - это скорее парадигма распределенной архитектуры / передачи сообщений / IPC / COM-esque.Последний был своего рода увлечением в 90-х и начале 2000-х, но с тех пор вымер.

Потоки и передача сообщений были фактически классическими дебатами в исследовании ОС в 90-х.Если вы хотите узнать больше об этом, вы должны прочитать об истории микроядер.Много усилий было потрачено на оптимизацию передачи сообщений, но, в конце концов, микроядры никогда не могли сравниться с производительностью монолитных ядер

...