我正在使用 flatbuffers 和 nng。使用 FB 我正在创建序列化缓冲区并将其添加到 nng msg。我想消除这种 FB 到 NNG 的复制。
为了实现这一点,我编写了一个自定义分配器,如下所示。
class CustomAllocator : public flatbuffers::Allocator
{
private:
nng_msg *m_nng_msg = nullptr;
public:
~CustomAllocator()
{
if (m_nng_msg) {
nng_msg_free(m_nng_msg);
m_nng_msg = nullptr;
}
}
nng_msg *get() { return m_nng_msg; }
nng_msg *release()
{
nng_msg *t_nng_msg = m_nng_msg;
m_nng_msg = nullptr;
return t_nng_msg;
}
uint8_t *allocate(size_t size) override
{
if (nng_msg_alloc(&m_nng_msg, size) != 0) {
return nullptr;
}
return static_cast<uint8_t *>(nng_msg_body(m_nng_msg));
}
void deallocate(uint8_t *p, size_t size) override
{
if (m_nng_msg) {
nng_msg_free(m_nng_msg);
m_nng_msg = nullptr;
}
}
};
然后将其附加到FB如下
CustomAllocator allocator;
flatbuffers::FlatBufferBuilder builder(1024, &allocator);
... fill using builder
nng_msg *msg = allocator.get();
nng_msg_trim(msg, nng_msg_len(msg) - builder.GetSize()); // this is required as FB adds data to the end of the buffer, i checked the *_trim and it does not do realloc
nng_msg_set_pipe(msg, pipe);
nng_sendmsg(s, msg, 0);
对于双重复制的情况,我像这样使用它
flatbuffers::FlatBufferBuilder builder(1024);
... fill using builder
nng_msg *msg = nullptr;
nng_msg_alloc(&msg, 0);
nng_msg_append(msg, builder.GetBufferPointer(), builder.GetSize());
nng_msg_set_pipe(msg, pipe);
nng_sendmsg(s, msg, 0);
我的期望是无副本会比双副本稍微好一点。但是当我进行测试时,我得到了不同的结果。
所以我想知道这种行为的原因可能是什么?
每个场景运行 20 次以获得平均时间。
Message Size 180 bytes
Message Count 20000 80000 100000
no-copy copy no-copy copy no-copy copy
time in ms 198 185 809 784 997 950
std-dev 47 44 85 66 72 83