我知道关于多线程通信的讨论很多,但是我没有发现涉及protobuf的通信。
背景:我最近编写了一个应用程序,其中使用protobuf在套接字之间进行通信。 我的应用程序产生了不同的线程,这些线程应该可以相互通信。
这是通过将对象(类的实例)推送到“ std :: queue”来完成的。 因此,基本上我一个线程使用我的信息创建了一个类的实例,将其推送到“队列”,而我的其他线程则从该队列(或缓冲区)中弹出对象并进行处理。
现在,我想知道使用“ protobuf”代替实例化对象进行通信是否会更好?
主要思想是创建一个protobuf消息,而不是一个类的整个实例,并将其推入队列。
因此,基本思想是创建一个“队列”,其中包含使用“ protobuf”方法SerializeToString()
生成的二进制字符串的列表。
这是在线程之间共享数据的更干净的方式(也是更有效的方式)吗?
答案 0 :(得分:1)
总结一下:使用方法1,您可以在std::queue
上使对象入队和出队。使用方法2,您仍将使用队列,但仅将对象的必要部分序列化到队列中。
最后,听起来就线程而言没有什么区别。生产者/消费者情况仍然相同。无论您使用哪种通信方式,客户端代码都不会更改。两种方法都不是“更清洁”。
方法1更有效。线程是为了优化而发明的,因此您可以共享内存。
方法1一次创建一个对象并将其销毁一次。方法2创建一个对象两次并将其销毁两次。该对象由生产者线程创建,然后将其序列化并销毁该对象。使用者线程根据反序列化的数据重新创建对象,该线程使用它然后销毁它。即使方法2可以以某种方式优化对象实例化(例如,使用char
数组而不是string
对象),也可以将相同的优化应用于方法1。
由于共享内存,方法1可以简单地读取对象。方法2必须将对象信息复制到缓冲区中,然后再将其复制回来。那是另外两个副本。
方法1有队列开销。通常,队列仅具有指向该对象的指针,因此排队和出队很便宜。队列可以在数组上实现。方法2还具有队列的开销。但是,数据全部存储在队列中,因此入队和出队取决于序列化数据的大小。即使序列化的数据很小,它也不会比方法1快。
方法1是共享内存多线程。方法2更多地是一种分布式体系结构/消息传递/ IPC / COM风格的范例。后者在90年代和2000年代初期颇为流行,但此后逐渐消失。
线程与消息传递实际上是90年代OS研究中的经典辩论。如果您想了解更多有关此的内容,则应阅读有关微内核的历史。在优化消息传递方面付出了很多努力,但最终,微内核永远无法匹敌单片内核的性能