什么是最好的方式来使用小数和日期时间与协议缓冲区?(What the best ways to us

2019-08-17 02:04发布

我想了解一下什么是存储了未包括在协议缓冲区支持列表中的一些常用的数据类型的最佳方式。

  • 日期时间(秒精度)
  • 日期时间(毫秒精度)
  • 具有固定精度小数
  • 具有可变精度小数
  • 大量的布尔值(如果你有很多很多,它看起来像你必须为每个1-2个字节的开销,因为它们的标签。

同样的想法是将它们映射很容易对应的C ++ / Python的/ Java数据类型。

Answer 1:

在protobuf的设计原理是最有可能保留的数据类型的支持,“原生”的可能,因此,很容易在未来采用新的语言。 我想他们也会在-建立的消息类型提供,但你在哪里划清界线呢?

我的解决方案是创建两个消息类型:

DateTime
TimeSpan

这仅仅是因为我来自一个C#的背景下,这些类型是理所当然的。

回想起来, TimeSpanDateTime可能已经矫枉过正,但它是避免从H / M / s至S和反之亦然的转换的“便宜”的方式; 这么说,这本来是简单到只实现一个实用功能,例如:

int TimeUtility::ToSeconds(int h, int m, int s)

BKLYN指出,堆存储器被用于嵌套消息; 在某些情况下,这显然是非常有效的 - 我们应该始终知道内存是如何使用的。 但是,在其他情况下,这可能是不太受关注,在这里我们担心更多的易于实施的(这是Java / C#理念,我想)的。

还有一个小缺点使用非固有的类型,与protobuf的TextFormat::Printer ; 你不能指定其所显示的格式,所以它会是这个样子:

my_datetime {
    seconds: 10
    minutes: 25
    hours: 12
}

......这是一些太冗长。 这就是说,它会更难读,如果它是以秒为单位表示。

最后,我想说:

  • 如果你担心内存/解析效率,使用秒/毫秒。
  • 然而,如果实现的简易性是目标,使用嵌套消息( DateTime等)。


Answer 2:

下面是根据我与类似Protocol Buffers的电线协议体验的一些想法。

日期时间(秒精度)

日期时间(毫秒精度)

我想答案这两个是相同的,你只是通常会处理以秒精度的情况下更小的范围内的数字。

使用sint64 / sfixed64在几秒钟内偏置/毫秒存储从午夜一样1/1/1970 GMT一些著名的时代。 这是如何Date对象是在Java中内部表示 。 我敢肯定有Python和C ++的类似物。

如果您需要时区信息,来传递您的日期/时间在UTC的条款和相关的时区建模为一个单独的字符串字段。 对于这一点,你可以使用标识符从奥尔森区信息数据库 ,因为已经变得有些标准。

这样,您有日期/时间的规范表示,但你也可以定位到任何时区相关。

具有固定精度小数

我首先想到的是用类似于一个如何构建从Python的十进制小数包对象的字符串。 我想这可能是相对于某个数值表示低效。

有可能是取决于你正在使用的域名是什么更好的解决方案。 例如,如果你正在制作一个货币价值,也许你可以逃脱使用UINT32 / 64连通在美分的价值,而不是分数的美元金额。

也有一些有益的建议此线程 。

具有可变精度小数

不Protocol Buffers的已经与浮点/双精度标量类型支持呢? 也许我误解了这个项目符号。

无论如何,如果你有必要去围绕这些标量类型,你可以编码使用IEEE-754(分别为浮动VS双)到UINT32 UINT64或。 例如Java 允许你提取的IEEE-754表现和反之亦然从浮点/双精度对象。 有在C ++ / Python的类似机制。

大量的布尔值(如果你有很多很多,它看起来像你必须为每个1-2个字节的开销,因为它们的标签。

如果您担心在电线上浪费字节,你可以使用的比特屏蔽技术对许多布尔压缩成一个UINT32 UINT64或。

因为没有在Protocol Buffers的一流的支持,所有这些技术都需要有点君子代理商之间的合同。 也许使用你的领域,如“_dttm”或“_MASK”的命名约定将有助于在某一领域具有超出协议缓冲的默认行为的其他编码的语义传达。



Answer 3:

对不起,不是一个完整的答案,而是一个“我也是”。

我觉得这是一个很大的问题,一个我很乐意回答自己。 由于无法本地描述基本类型,如日期时间和(对于财务应用程序)定点小数,或将它们映射到语言指定或用户定义类型对我是一个真正的杀手锏。 它由能够使用图书馆,我认为并非如此是太棒了或多或少阻止我。

在原语法声明自己的“日期时间”或“定点”的消息是不是一个真正的解决方案,因为你仍然需要你的平台的代表从生成的对象手动转换为/,这是很容易出错。 另外,当底层的类型基本上是一个64位的整数这些嵌套消息能存储作为指针在C ++中,这是低效的似地堆分配对象。

具体来说,我希望能够写出这样的事情在我的原文件:

message Something {
   required fixed64 time = 1 [cpp_type="boost::posix_time::ptime"];
   required int64 price = 2 [cpp_type="fixed_point<int64_t, 4>"];
   ...
 };

而且我会被要求提供任何胶水是必要的,这些类型从fixed64和Int64的转换/让序列化是可行的。 也许直通类似土坯::推广 ?



Answer 4:

对于毫秒级的日期时间我使用int64具有日期时间为YYYYMMDDHHMMSSmmm 。 这使得既简洁又可读,和令人惊讶的,将持续很长一段时间。

对于小数,我使用byte[]知道有没有更好的表现,这将不会是有损耗的。



文章来源: What the best ways to use decimals and datetimes with protocol buffers?