【问题标题】:FlatBuffers Storage/Size GuaranteesFlatBuffers 存储/大小保证
【发布时间】:2019-05-20 04:52:08
【问题描述】:

FlatBuffers 特别避免了某些编码标准化/保证。根据文档:

(https://google.github.io/flatbuffers/flatbuffers_internals.html)

这可能意味着两种不同的实现可能会产生不同的 给定相同输入值的二进制文件,这是完全有效的。

好的,但是字符串是直接从给定的任何表示形式在磁盘上编码的,还是以其他表示形式编码的?是否使用相同的 FlatBuffers 版本和生成的代码确定性的编码操作(具有相同参数的 N 次操作产生相同的结果)?

尺寸呢?动态结构大小的减小(例如向量、字符串值被缩短)是否会相应地减小编码结构的大小?

我真的不明白字符串编码是如何工作的,我现在没有时间拆开内部代码。

我创建了一个示例定义,它具有一般的 parent->child->grandchild 结构,其中 parent 类型具有 child 类型的向量,而 grandchild 类型嵌入了一个字符串以及一个 struct。我想通过包含其中的几个来夸大不同类型的值可能会引入输出大小的任何熵。然后,我用 5 个符文字符串乘以 50 填充 grandchild 中的字符串值,并手动将乘数递减 1,并每次打印最终编码的输出大小:

$ go run main.go
String size: (250)
Output encoding size: (400)

$ go run main.go
String size: (245)
Output encoding size: (400)

$ go run main.go
String size: (240)
Output encoding size: (392)

$ go run main.go
String size: (235)
Output encoding size: (384)

为什么在我从原始字符串值中删除五个字节后,编码的输出大小没有改变?为什么我从原始字符串中每删除五个字节,它就会缩小八个字节?由于这些是字符串,因此我认为对齐不会在这里发挥作用。

我仍然有上述问题,但似乎可能是一个安全的假设(呃,保证)1)编码的大小对于相同的参数是稳定的,2)将随着其中一个或多个值大小的减小而缩小。这是真的吗?

感谢您为我节省了一些时间和错误,我现在不必自己解决这个问题(希望如此)。

作为参考,这是定义:

namespace testformat;

struct Vector {
    field9:ulong;
    field10:ulong;
    field11:ulong;
}

table Grandchild {
    field5:ulong;
    string6:string;
    field7:ulong;
    field8:Vector;
}

table Child {
    field3:ulong;
    field4:ulong;
    grandchild:Grandchild;
}

table Parent {
    field1:ulong;
    field2:ulong;
    children:[Child];
}

root_type Parent;

这是我更改的重复字符串值的部分 Go 代码(在顶部):

stringValue := strings.Repeat("strin", 50)
fmt.Printf("String size: (%d)\n", len(stringValue))

stringOffset := b.CreateString(stringValue)

testformat.GrandchildStart(b)

testformat.GrandchildAddField5(b, 44)
testformat.GrandchildAddString6(b, stringOffset)
testformat.GrandchildAddField7(b, 55)

vectorOffset := testformat.CreateVector(b, 11, 22, 33)
testformat.GrandchildAddField8(b, vectorOffset)

grandchildOffset := testformat.GrandchildEnd(b)

【问题讨论】:

    标签: flatbuffers


    【解决方案1】:

    这包含很多问题,所以这里有一些答案:

    • 字符串:FlatBuffers 将这些存储为 UTF-8,因此在输入已经可以是 UTF-8 的语言中(例如通常在 C++ 中),序列化此数据是一个直接副本,无需任何处理。在使用其他表示的语言(如 Java)中,序列化时有一个转换步骤。
    • 调整大小:是的,减小向量的大小通常会减小缓冲区的大小,但不一定相等。例如,如果您有一个短裤向量,则将大小减少 1 个元素可能会将缓冲区减少 0 或 4,具体取决于对齐方式。
    • 在您的实验中,您再次看到了对齐和填充的效果。一切都与它自己的大小对齐(几乎所有编程语言都将数据存储在内存中)。因此,如果您的缓冲区包含 doublelong 或其他任何内容,则缓冲区的大小只会以 8 字节的增量变化。字符串的大小是 4 字节对齐的,但实际的字符串数据只有 1 字节对齐,因此可以在不改变缓冲区大小的情况下向字符串添加字符,因为它只是使用了更多以前的内容填充字节。即使字符串字节不需要对齐,相邻的数据也可以。
    • 1:仅当顺序相同或语言/实现相同时。某些实现可能会更改影响对齐和填充的顺序。
    • 2:如上所示,缓冲区大小的减少仅与元素的减少间接相关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多