【问题标题】:Using flatbuffers struct as a key使用 flatbuffers 结构作为键
【发布时间】:2019-08-20 00:57:44
【问题描述】:

我正在考虑使用 flatbuffers 的序列化 struct 作为键值存储中的键。这是我想在 RocksDB 中用作键的 structs 示例。

struct Foo {
  foo_id: int64;
  foo_type: int32;
}

我阅读了文档并认为struct 的布局是确定性的。这是否意味着它适合用作钥匙?如果是,我如何序列化 struct 并将其反序列化。 Table 似乎有用于序列化/反序列化的 API,但 struct 没有(?)。

我尝试序列化 struct 这样做如下:

constexpr int key_size = sizeof(Foo);
using FooKey = std::array<char, key_size>;

FooKey get_foo_key(const Foo& foo_object) {
  FooKey key;
  std::memcpy(&key, &foo_object, key_size);
  return key;
}

const Foo* get_foo(const FooKey& key) {
  return reinterpret_cast<const Foo*>(&key);
}

我做了一些健全性检查,上面的内容似乎在我的 Ubuntu 18 docker 映像中工作,并且速度非常快。所以我的问题如下:

  1. 如果机器通过了 FLATBUFFERS_LITTLEENDIAN 和 uint8/char 等效性检查,那么在机器上执行此操作是否安全?还是需要进行其他检查?

  2. 在执行上述操作时,我还应该注意哪些其他注意事项?

提前致谢!

【问题讨论】:

    标签: flatbuffers


    【解决方案1】:

    您实际上不需要通过std::arrayFoo 结构已经是一块内存,可以根据需要安全地复制或转换。它不需要序列化函数。

    就像你说的,内存包含小端数据,所以 FLATBUFFERS_LITTLEENDIAN 必须通过。实际上,即使在大端机器上,您也可以复制所有您想要的结构,只要您使用访问器读取字段(在大端访问时执行字节交换)。唯一不适用于大端的是将结构转换为 int64_t * 以在不使用访问器方法的情况下读取第一个字段。

    对某些强制转换操作的另一个警告是严格的别名,如果你打开了某些强制转换可能是未定义的行为。

    另请注意,在此示例中,Foo 在所有平台上的大小都是 16 字节,因为对齐。

    【讨论】:

    • 感谢您澄清这一点。您能否评论一下使用上述结构作为键是否安全。也就是说,一个给定的结构对象将只有一个序列化表示,反之亦然。我认为是这样。但是从 flatbuffers 贡献者那里听到的话会让我更有信心。 :)
    • 是的,使用它作为密钥应该是安全的,因为二进制表示应该始终相同。甚至在结构中使用0s 进行显式填充以确保这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 2020-06-20
    • 1970-01-01
    相关资源
    最近更新 更多