rem*_*emv 4 c++ serialization boost boost-asio zeromq
我有一个应用程序,我希望通过网络将其部分可变状态发送到另一台机器(将有一组这些机器)对其进行一些CPU密集型计算并获取结果.像异步RPC一样.这样的调用将在程序执行期间多次发生,因此我希望尽量减少开销,例如最小化数据冗余副本的数量.数据大小从几十字节到几百KB不等,甚至可能只有几MB.它的结构相对复杂,它由一组对象树组成,但是叶子只包含原始类型,而内部节点包含最少的元数据.
我正在考虑Cap'n Proto进行序列化(但是,在这种情况下,我必须为我的数据创建一个冗余模型),而ZeroMQ用于传输.在客户端/主应用程序端,我想使用azmq,因为我需要Boost:Asio的功能(即协程/光纤支持).语言是C++.
总结一个非常粗略的草图:
RelativelyComplexState data;
CapnProtoRequest cp_req = buildRequest(data); // traverses my data, creates C'n P object
azmq_socket.async_send(boost::asio::buffer(cp_req, cp_req.size)); //azmq always copies the buffer? Not good.
// do other stuff while request is being processed remotely
// get notification from azmq/Boost:Asio when reply has arrived
azmq::message msg();
azmq_socket.async_receive(some_message_handler?); // get all the data into msg
CapnProtoResponse cp_resp = parseResponse(msg.cbuffer()); // interpret bytes as C'n P object, hopefully no copy
RelativelySimpleResult result = deserialize(cp_resp);
Run Code Online (Sandbox Code Playgroud)
这是可行的,还是有更好的方法?在这种情况下,无模式序列化方法(即Boost :: Serialization)是否会使我的生活更轻松和/或应用程序更高效?
另外,使用ZeroMQ/azmq发送和接收Cap'n Proto对象的最佳方法是什么,避免不必要的副本?通过查看azmq的源代码,似乎对于发送,azmq总是复制缓冲区内容.有哪些更微妙的问题(细分/框架等)?我不熟悉这些库,也没有找到任何解释或好的例子.
谢谢!
我对ZeroMQ的界面了解不多,但我可以就如何最大限度地减少Cap'n Proto的副本提出建议.
在发送方面,使用capnp::MessageBuilder::getSegmentsForOutput()(capnp/message.h)直接指向消息的内容而不复制.这为您提供了一个字节数组(实际上是单词,但您可以将它们转换为字节).你需要以某种方式将这些提供给ZeroMQ而不复制它们.您需要确保保留段之间的边界 - 目标是在接收端提供完全相同的阵列数组.也许ZeroMQ明确支持多段消息,并且可以为您记住段边界; 如果没有,您需要在邮件前添加一个段大小表.
在接收端,一旦重建了段数组,构造一个capnp::SegmentArrayMessageReader(capnp/message.h)并将数组传递给构造函数.这将使用基础数据而无需复制.(请注意,您需要确保数据在64位边界上对齐.我不确定ZeroMQ是否保证这一点.)
请注意,如果您的客户端和服务器都是C++,您可能需要考虑使用Cap'n Proto自己的RPC协议,它更容易设置并且已经避免了所有不必要的副本.然而,整合Cap'n Proto的事件循环boost::asio目前并非易事.这是可能的 - 例如,您可以查看将Cap'n Proto与libuv的事件循环集成的node-capnp - 但可能比您想做的更多.
(披露:我是Cap'n Proto的作者.)
| 归档时间: |
|
| 查看次数: |
848 次 |
| 最近记录: |