tunm, 一种对标JSON的二进制数据协议
Tunm
simple binary proto
一种对标JSON的二进制数据协议
支持的数据类型
基本支持的类型 "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "varint", "float", "string", "raw", "array", "map"
各种数值类型格式说明
- u8/i8 用一个字节进行写入
- u16/i16/u32/i32/u64/i64 分别对应大小的数据写入, 小端模式
- float 精度只有3位小数, 当成*1000的u32处理
- double 精度只有6位小数, 当成*1000000的u64数据
- varint 可变长的整型数据
如果是正数则*2, 如果是负数则-(x + 1) * 2, 相当于0->0, -1->1, 1->2,-2->3,2->4来做处理, 因为是小子节的数比较多, 每bit里的第一位则表示是否是最后一位, 如果10000001, 则表示还要继续往下读如果是00000001则表示这是最后一位
- str 字符串类型, 则先用varint表示str的长度, 然后再写入str的值
- str_idx 字符串索引值, 在str的arr表中的第几位, 重复的str则在同一个位置, 用varint表示
- array 数组类型, 先用varint表示array的长度, 然后再写入各个value的数值
- map map类型, 先用varint表示map的长度, 然后先写入key, 再写入value, 依次循环到结束
与protobuf差异
相对protobuf, 无需预先定义任何的数据格式, 更好的适应多变的场景, 或者客户端不好更新的情况, 拥有更好的自适应性, 简单开封即用, 和JSON一样, 在可支持的数据类型里, 可以自由的进行转换
与JSON的差异
可以把这个看做是二进制的JSON格式, 有更好的压缩率和更快的解析速度
数据使用, 以Rust为例
extern crate tunm_proto as tunm;
use tunm::{Value, Buffer};
mod test_data;
use std::collections::{HashMap};
fn main()
{
println!("welcome to tickdream rust protocol");
let mut hash_value = HashMap::<Value, Value>::new();
hash_value.insert(Value::Str("name".to_string()), Value::Str("tunm_proto".to_string()));
hash_value.insert(Value::Str("tunm_proto".to_string()), Value::U16(1 as u16));
{
let mut buffer = Buffer::new();
tunm::encode_proto(&mut buffer, &"cmd_test_op".to_string(), vec![Value::Map(hash_value.clone())]).unwrap();
let just_str = "
[\"cmd_test_op\", [\"tunm_proto\", {\"name\": \"tunm_proto\", \"tunm_proto\": 1}]]
";
println!("just json len = {}", just_str.len());
println!("buffer len == {}", buffer.data_len());
// just read field
let read = tunm::decode_proto(&mut buffer).unwrap();
match read {
(name, val) => {
assert_eq!(name, "cmd_test_op".to_string());
assert_eq!(val[0], Value::Map(hash_value));
assert_eq!(val.len(), 1);
}
}
}
}
格式说明
数据协议分为三部分(协议名称, 字符串索引区, 数据区(默认为数组))
如数据协议名为cmd_test_op, 数据为["tunm_proto", {"name": "tunm_proto", "tunm_proto": 1}]
- 那么数据将先压缩协议名cmd_test_op, 将先写下可变长度(varint)值为11占用1字节, 然后再写入cmd_test_op的utf8的字节数
- 接下来准备写入字符串索引区, 索引数据用到的字符串为["tunm_proto", "name"]两个字符串, 即将写入可变长度(varint)值为2占用一字节, 然后分别写入字符串tunm_proto和name两个字符串, 这样子字符串相接近有利于压缩, 且如果有相同的字符串可以更好的进行复用
- 接下来准备写入数据区,
首先判断为一个数组, 写入类型u8(TYPE_ARR=16), 写入数组长度varint(2), 准备开始写第一个数据, 字符串tunm_proto, 已转成id, 则写入类型u8(TYPE_STR_IDX=14), 查索引号0, 则写入varint(0), 第一个字段写入完毕, 接下来第二个字段是一个map数据, 写入map长度varint(2), 然后进行遍历得到key值为name, 则写入写入类型u8(TYPE_STR_IDX=14),查索引号1, 则写入varint(1), 然后开始写name对应的值tunm_proto, 写入TYPE_STR_IDX类型的0值, 则这组key写入完毕, 依此类推写入第二组数据
测试打印的结果
用完整的level-full4.json
原始的JSON长度 = 2.2M
解析JSON用时 = Ok(1.520187s)
用tunm_proto压缩test_level4_json的长度 = 370k
压缩JSON耗时 = Ok(31.842ms)
name = cmd_level4_full
解析buffer耗时 = Ok(22.642ms)
解析速度约为JSON的68倍, 符合预期, 大小为明文的0.16倍, 符合压缩比
相关连接
协议地址https://github.com/tickbh/TunmProto
tunm, 一种对标JSON的二进制数据协议的更多相关文章
- SSH返回Json格式的数据
在开发中我们经常遇到客户端和后台数据的交互,使用比较多的就是json格式了.在这里以简单的Demo总结两种ssh返回Json格式的数据 项目目录如下 主要是看 上图选择的部分 WebRoot里面就 ...
- Atitit. 二进制数据ascii表示法,与base64编码解码api 设计标准化总结java php c#.net
Atitit. 二进制数据ascii表示法,与base64编码解码api 设计标准化总结java php c#.net 1. Base64编码, 1 1.1. 子模式 urlsafe Or url ...
- Atitit. 二进制数据ascii表示法,与base64编码解码api 设计标准化总结java php c#.net
Atitit. 二进制数据ascii表示法,与base64编码解码api 设计标准化总结java php c#.net 1. Base64编码,1 1.1. 子模式 urlsafe Or url u ...
- Erlang 位串和二进制数据
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25876834&id=3300393 因为在本人工作中,服务端Erla ...
- C#.NET序列化XML、JSON、二进制微软自带DLL与newtonsoft(json.net)
序列化是将对象转换成另一种格式(XML.json.二进制byte[]) JSON序列化 .NET中有三种常用的JSON序列化的类,分别是: Newtonsoft.Json.JsonConvert类(推 ...
- (转)Unity3D研究院之将场景导出XML或JSON或二进制并且解析还原场景
自:http://www.xuanyusong.com/archives/1919 导出Unity场景的所有游戏对象信息,一种是XML一种是JSON.本篇文章我们把游戏场景中游戏对象的.旋转.缩放.平 ...
- 将场景导出XML或JSON或二进制而且解析还原场景
导出unity场景的全部游戏对象信息,一种是XML一种是JSON. 本篇文章我们把游戏场景中游戏对象的.旋转.缩放.平移与Prefab的名称导出在XML与JSON中.然后解析刚刚导出的XML或JSON ...
- Ajax的三种实现及JSON解析
本文为学习笔记,属新手文章,欢迎指教!! 本文主要是比较三种实现Ajax的方式,为以后的学习开个头. 准备: 1. prototype.js 2. jquery1.3.2.min.js 3. j ...
- Json传递数据两种方式(json大全)
1.Json传递数据两种方式(json大全)----------------------------字符串 var list1 = ["number","name&quo ...
- 几种常用的json序列化和反序列化工具介绍
一.前言 Json序列化和反序列化工作中会时常用到,也是目前数据交互的常用格式,Rest风格的接口加上json格式的数据交互,真的是天作之合. 目前Json字符与Json对象的相互转换方式有很多,接下 ...
随机推荐
- LeetCode 周赛 352(2023/07/02)一场关于子数组的专题周赛
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 [BaguTree Pro] 知识星球提问. 往期回顾:LeetCode 单周赛第 350 场 · 滑动窗口与离 ...
- Matlab2014a 找不到 vs2015编译器解决方法
准备工作 前提: 电脑已经安装 1.Matlab版本2014a 2.VS版本2015 目标: 结合Matlab和VS2015,实现Matlab的GUI文件和.m文件转化为.exe文件,然后可以单独运行 ...
- 我真的,AI框架的编程范式怎么理解?
我给领导汇报AI框架用函数式编程好,没讲明白,说函数式就是写函数那样方便,都被领导吊飞了,啥玩意,写啥不是写函数,狗屁不通! 网上搜说用tensorflow那就是用声明式编程,用pytorch就是命令 ...
- Cilium 系列-3-Cilium 的基本组件和重要概念
系列文章 Cilium 系列文章 前言 安装完了,我们看看 Cilium 有哪些组件和重要概念. Cilium 组件 如上所述,安装 Cilium 时,会安装几个运行组件(有些是可选组件), 它们各是 ...
- Cilium系列-5-Cilium替换KubeProxy
系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, ...
- 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(10.A)- FlexSPI NAND启动时间(RT1170)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 FlexSPI NAND启动时间. 本篇是 i.MXRT1170 启动时间评测第四弹,前三篇分别给大家评测 ...
- 【go语言】2.4.3 Go Modules
Go Modules 是 Go 语言的官方依赖管理工具,自 Go 1.11 版本开始引入.它解决了 Go 语言在依赖管理上的一些问题,如版本控制.依赖隔离等. 初始化一个新的模块 你可以使用 go m ...
- quarkus依赖注入之四:选择注入bean的高级手段
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<quarkus依赖注入> ...
- [golang]使用gocron编写定时任务
前言 linux自带的crontab默认情况下只能精确到分钟,没法执行秒级任务.当然,也不是不行,比如: * * * * * for i in $(seq 1 11);do echo hello &g ...
- 《深入理解Java虚拟机》读书笔记:字节码指令简介
字节码指令简介 Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成.由于Jav ...