乐趣区

Unity-Protobuf和JSON对比

Protobuf

什么是 Protobuf?
Protobuf(Protocal buffer)是 google 的一种数据交换的格式,基于二进制,跨语言、跨平台。

在 Unity 中使用 Protobuf
两种方式:
1. 导入 Unity 专用的 Protobuf-net 资源包,用 C# 代码定义对象。
2. 配置.net 的 Protobuf 环境,用原生的.proto 文件定义对象。

这里测试选用的是第一次种方式。
protobuf-net.unitypackage 链接:https://pan.baidu.com/s/1DBD4… 提取码:trl4

Protobuf 解析代码封装:

using System.IO;
using ProtoBuf;

/// <summary>
/// Protobuf 解析工具类
/// ZhangYu 2019-05-24
/// <para>blog:https://segmentfault.com/a/1190000019875130</para>
/// </summary>
public class PBParser {

    /// <summary> 序列化 </summary>
    public static byte[] To<T>(T entity) {byte[] result = null;
        if (entity != null) {using (MemoryStream stream = new MemoryStream()) {Serializer.Serialize<T>(stream, entity);
                result = stream.ToArray();}
        }
        return result;
    }

    /// <summary> 反序列化 </summary>
    public static T From<T>(byte[] message) {T result = default(T);
        if (message != null) {using (MemoryStream stream = new MemoryStream(message)) {result = Serializer.Deserialize<T>(stream);
            }
        }
        return result;
    }
}

参考资料:
《Unity3D protobuf-net 使用方式》https://www.cnblogs.com/mrblu…
《unity 中使用 protobuf-net》https://blog.csdn.net/kenkao/…
《Protobuf 的使用流程》https://www.cnblogs.com/guxin…

JSON

什么是 JSON?
JSON(JavaScript Object Notation,JS 对象表示法)是一种轻量级的数据交换格式,基于文本,跨语言、跨平台。
JSON 拥有简洁、易独写的特点。

一个简单的 JSON:

{
    "id":1,
    "username":"zhangyu",
    "password":"123456"
}

参考资料:
《JSON 教程》https://segmentfault.com/a/11…

Protobuf 和 JSON 对比

测试对象:

using ProtoBuf;

[ProtoContract]
public class TestVo {[ProtoMember(1)]
    public uint id;
    [ProtoMember(2)]
    public string username;
    [ProtoMember(3)]
    public string password;
    [ProtoMember(4)]
    public string nickname;
    [ProtoMember(5)]
    public byte lv;
    [ProtoMember(6)]
    public float hp;
    [ProtoMember(7)]
    public float mp;
    [ProtoMember(8)]
    public int exp;

}

测试代码:

private void TestVo() {TestVo vo = new TestVo();
    vo.id = 1000001;
    vo.username = "zhangyu";
    vo.password = "password";
    vo.nickname = "冰封百度";
    vo.lv = 100;
    vo.hp = 99999f;
    vo.mp = 88888f;
    vo.exp = 9999999;
    vo.isOnline = true;

    // Json
    string json = JsonUtility.ToJson(vo);
    byte[] jsBytes = Encoding.UTF8.GetBytes(json);
    print("Json:" + json);
    print("Json bytes:" + BitConverter.ToString(jsBytes));

    // Protobuf
    byte[] pbBytes = PBParser.To(vo);
    print("Protobuf bytes:" + BitConverter.ToString(pbBytes));

    // Compare Length
    print("Json length:" + jsBytes.Length);
    print("Protobuf length:" + pbBytes.Length);
    
    // 输出结果:// Json:{"id":1000001,"username":"zhangyu","password":"password","nickname":"冰封百度","lv":100,"hp":99999.0,"mp":88888.0,"exp":9999999,"isOnline":true}
    // Json bytes:7B-22-69-64-22-3A-31-30-30-30-30-30-31-2C-22-75-73-65-72-6E-61-6D-65-22-3A-22-7A-68-61-6E-67-79-75-22-2C-22-70-61-73-73-77-6F-72-64-22-3A-22-70-61-73-73-77-6F-72-64-22-2C-22-6E-69-63-6B-6E-61-6D-65-22-3A-22-E5-86-B0-E5-B0-81-E7-99-BE-E5-BA-A6-22-2C-22-6C-76-22-3A-31-30-30-2C-22-68-70-22-3A-39-39-39-39-39-2E-30-2C-22-6D-70-22-3A-38-38-38-38-38-2E-30-2C-22-65-78-70-22-3A-39-39-39-39-39-39-39-2C-22-69-73-4F-6E-6C-69-6E-65-22-3A-74-72-75-65-7D
    // Protobuf bytes:08-C1-84-3D-12-07-7A-68-61-6E-67-79-75-1A-08-70-61-73-73-77-6F-72-64-22-0C-E5-86-B0-E5-B0-81-E7-99-BE-E5-BA-A6-28-64-35-80-4F-C3-47-3D-00-9C-AD-47-40-FF-AC-E2-04-48-01
    // Json length:148
    // Protobuf length:56
}

测试结果:
Protobuf 比 JSON 小。
而从其他参考资料和测试结果来看:Protobuf 比 JSON 速度快,体积小。JSON 比 Protobuf 可读性强,易用性强。

结果分析:
Protobuf 是基于二进制的,JSON 是基于文本格式的,原理上决定了 Protobuf 速度会更快,体积会更小。
但是 JSON 毕竟发展很久了,用的更广泛,使用项目众多,类库众多,有些库经过深度优化,速度非常快了。在某些细节点上,性能不输于 Protobuf,甚至更好。
用某几个高度优化的细节去对比 JSON 和 Protobuf 的性能,有些不客观,整体上来说,Protobuf 比 JSON 性能要高不少,高数倍到十数倍。

Json 和 Protobuf 该如何选择?
小孩子才做选择题,成年人当然是全都要。
个人建议:在对大小和性能不敏感时用 JSON,敏感时用 Protobuf。
比如本地写配置文件时用 JSON,易读易修改。网络传输对象数据时用 Protobuf,减小数据量。

参考资料:
《全方位评测:Protobuf 性能到底有没有比 JSON 快 5 倍?》https://blog.csdn.net/xiaoxia…

闲聊:
在信息爆炸的时代,互联网技术突飞猛进,总会有各种各样的新技术、新工具出现,这是大势所趋,无法阻挡。
如果有哪天出现了比 JSON 更方便、比 Protobuf 更小的数据格式,我毫不意外,只会欣喜。
我们要拥抱这种变化,对我们来说是好事,这些新技术、新工具的出现,让我们的工作变得更方便、更效率、更强大了。
当然,这些新出现的技术和工具也需要我们消耗更多的时间去了解、熟悉、精通。取其精华,去其糟粕即可。

从数据格式来讲,从刚开始接触 XML 打开了新世界的大门,到见到 JSON 时的惊艳,再到知道 Protobuf 时的好奇。
发现这些数据格式都是为了完成某些特殊功能而实现的,适用环境不同,各有优略,很难做到完全替代,选择更适合的就好。
基本上分为两大类:
1. 便于人使用
2. 便于网络传输
第一种便于人使用的数据格式,趋向于更简洁的语法,多是基于文本格式的,给人读的。
第二种便于网络传输的数据格式,趋向于更小的体积,给计算机读的。

第一种格式也许有哪一天会发展到成为全世界通用的语言,比现在的英语更容易理解,和学习阿拉伯数字 0 - 9 的难度相差不大,甚至可以作为儿童启蒙语言。
第二种格式会进化到完全基于二进制 bit 来表示对象,数据极其紧凑,体积极小,基本无垃圾数据,没什么可压缩的空间。
PS: 作者 ZhangYu 2019-07-25 看看人类需要多少年才能实现这两种格式。

退出移动版