|
jsonc库通过将json格式压缩为二进制来提高性能。我当时想性能肯定秒杀其他json库,但还是我太傻太年轻。我很快就发现了不对劲的地方。
我简单的对比了一下二进制和文本解析性能,发现两者之间差距没有想象的那么大,只有很少的性能提升。因为时间主要花在内存分配上,而不是解析本身。如果要优化性能,可能需要自定义分配器。这玩意儿继续优化下去,完全失去了代码量少的优势。虽然我没有和Rapidjson对比过性能,但自己吹的牛逼,硬着头皮也要想办法。
于是我又有了一个新的想法。之前的格式都是以压缩率最大化来设计的,根本没有考虑到解析的性能。如果能保持运行时内存和持久化内存同构,就能实现解析性能的最大化。我很快设计并实现了第二版的格式,实现了零开销的解析。
两个版本和JSON文本格式的性能对比:
格式 | 压缩率 | 解析开销 | version 1 | 20% | 50% | version 2 | 90% | 0 | 第一个版本,压缩率最大化,解析耗时是原来的50%。第二个版本性能最大化,和原来的大小差不多,解析耗时是0。
为什么时间是0呢,解析时其实只做了一次指针的跳转,代码像这样:
static Value *decode(char *buffer, int size) {
int32_t *jmp = (int32_t*)buffer;
if (*jmp > size) return NULL;
return (Value*)(buffer + *jmp);
}其实这个跳转也能想办法省略,但这样已经是0耗时了。jsonc中两个版本同时支持,根据自己的需求选择。
其他优势
jsonc既有文本格式的优点,却没有json的缺点。对json只是压缩,不改变语义。除了压缩率和解析性能以外,这么做的好处:
- 1.很容易在二进制和json格式之间互转,而不产生潜在bug。例如游戏在开发阶段使用文本格式,发布时使用二进制格式来提高性能,格式切换后并不需要做大量可靠性测试。
- 2.在代码中使用相同的数据接口,这让两种序列化方式共享相同代码。你可以通过请求参数来控制服务端返回文本格式还是二进制格式,同时支持两种格式不会增加代码量。
- 3.即使服务端不用双格式支持,对二进制格式有任何debug需求,也可以通过自带的工具将二进制转成文本格式。不需要schema接口定义文件。对可读性伤害较小。
- 4.即使维护旧服务,不想动旧代码。也可以在代理服务上包一层,将文本json转成二进制格式。这样能提高客户端性能,和节省用户流量。
源码见这里: |
|