Chapter 2 - Sockets and Patterns【选译,哈哈】 Part 9 Zero-Copy

Zero-Copy

ZeroMQ的消息API允许您直接从应用程序缓冲区发送和接收消息,而无需复制数据。我们称之为零拷贝,它可以在某些应用程序中提高性能。

在以高频率发送大块内存(数千字节)的特定情况下,应该考虑使用零复制。对于短消息或较低的消息率,使用零复制将使您的代码更混乱和更复杂,没有可衡量的好处。与所有优化一样,当您知道它有帮助时,请使用它,并在前后进行测量。

要进行零复制,可以使用zmq_msg_init_data()创建一条消息,该消息引用已经由malloc()或其他一些分配器分配的数据块,然后将其传递给zmq_msg_send()。在创建消息时,还传递了一个函数,ZeroMQ在完成消息发送后将调用该函数释放数据块。这是最简单的例子,假设buffer是一个分配在堆上的1,000字节的块:

void my_free (void *data, void *hint) {
    free (data);
}
//  Send message from buffer, which we allocate and ZeroMQ will free for us
zmq_msg_t message;
zmq_msg_init_data (&message, buffer, 1000, my_free, NULL);
zmq_msg_send (&message, socket, 0);

注意,在发送消息后不要调用zmq_msg_close()。libzmq将在实际发送消息时自动执行此操作。

没有办法在接收时进行零拷贝:ZeroMQ向您提供一个缓冲区,您可以随意存储该缓冲区,但它不会直接将数据写入应用程序缓冲区。

在编写时,ZeroMQ的多部分消息与零拷贝很好地结合在一起。在传统的消息传递中,您需要将不同的缓冲区封送到一个可以发送的缓冲区中。这意味着复制数据。使用ZeroMQ,您可以将来自不同来源的多个缓冲区作为单独的消息帧发送。将每个字段作为长度分隔的帧发送。对于应用程序来说,它看起来像是一系列发送和接收调用。但是在内部,多个部分被写入网络,然后通过单个系统调用进行回读,因此非常高效。

posted @ 2021-09-26 09:44  水色天空  阅读(47)  评论(0编辑  收藏  举报