gzipped json 与高效二进制序列化的性能

Performance of gzipped json vs efficient binary serialization

JSON 和 Gzip 是一种序列化数据的简单方法。这些在编程语言中被广泛实现。此外,这种表示形式可以跨系统移植(是吗?)。

我的问题是,与非常高效的二进制序列化方法相比,json+gzip 是否足够好(成本低于 2 倍)?我在序列化各种数据时寻找 space 和时间成本。

使用 json+gzip 序列化比 rawbytes+gzip 多使用 25% space 用于数字和对象。对于精度有限的数字(4 位有效数字),序列化大小是相同的。似乎对于小规模应用程序,就数据大小而言,使用 json+gzip 就足够了。即使在发送记录数组时也是如此,其中每条记录都完整地拼出了字段和值(JavaScript 中存储数据的常用方式)。

以下实验的来源:https://github.com/csiz/gzip-json-performance

数字

我选择了一百万个浮点数(64 位)。我假设这些数字来自某些自然来源,所以我使用指数分布生成它们,然后将它们四舍五入为 4 位有效数字。因为 JSON 写下了整个表示,我认为存储大量数字可能会产生更大的成本(例如,存储 123456.000000 与 0.123456)所以我检查了这两种情况。我还检查未四舍五入的序列号。

在序列化小数字时,压缩 json 使用的大小比压缩二进制大 9%(数量级约为 1.0,因此只需写下几位数字):

json 3.29mb json/raw 43%
binary 3.03mb binary/raw 40%
json/binary 1.09

压缩后 json 使用的大小比序列化大数字时压缩二进制小 17%(数量级约为 1000000,需要写下更多数字):

json 2.58mb json/raw 34%
binary 3.10mb binary/raw 41%
json/binary 0.83

压缩后 json 使用的大小比序列化全精度双精度时压缩二进制文件大 22%:

json 8.90mb json/raw 117%
binary 7.27mb binary/raw 95%
json/binary 1.22

对象

对于对象,我在 JSON 中以通常的惰性方式对它们进行序列化。每个对象都存储为带有字段名称和值的完整记录。 "choice" 枚举的值已完整说明。

[
  {
    "small number": 0.1234,
    "large number": 1234000,
    "choice": "two"
  },
  ...
]

为了高效的二进制表示,我将对象矢量化。我存储对象的数量,然后是小数字的连续向量,然后是选择枚举的连续向量。在这种情况下,我假设枚举值是已知的并且是固定的,所以我将索引存储到这个枚举中。

n = 1e6
small number = binary([0.1234, ...])
large number = binary([1234000, ...])
choice = binary([2, ...]) # indexes to the enum ["zero", "one", ..., "four"]

在存储对象时,压缩 json 使用的大小比压缩二进制大 27%:

json 8.36mb json/raw 44%
binary 6.59mb binary/raw 35%
json/binary 1.27