Serialization 性能实体序列化:BSON vs MessagePack(vs JSON)

Serialization 性能实体序列化:BSON vs MessagePack(vs JSON),serialization,deserialization,bson,msgpack,messagepack,Serialization,Deserialization,Bson,Msgpack,Messagepack,最近我发现了,这是Google的另一种二进制序列化格式,它的性能也优于这两种格式 还有MongoDB用于存储数据的序列化格式 有人能详细说明BSON和MessagePack的区别和优势吗 只需完成性能二进制序列化格式的列表:还有一些将成为Google协议缓冲区的继任者。然而,与所有其他提到的格式相比,这些格式并不与语言无关,并且依赖于Go,至少在Go以外的其他语言上也有Gobs库。//请注意,我是MessagePack的作者。这个答案可能有失偏颇 格式设计 与JSON的兼容性 尽管名称不同,B

最近我发现了,这是Google的另一种二进制序列化格式,它的性能也优于这两种格式

还有MongoDB用于存储数据的序列化格式

有人能详细说明BSON和MessagePack的区别和优势吗



只需完成性能二进制序列化格式的列表:还有一些将成为Google协议缓冲区的继任者。然而,与所有其他提到的格式相比,这些格式并不与语言无关,并且依赖于Go,至少在Go以外的其他语言上也有Gobs库。

//请注意,我是MessagePack的作者。这个答案可能有失偏颇

格式设计

  • 与JSON的兼容性

    尽管名称不同,BSON与JSON的兼容性不如MessagePack

    BSON有一些特殊类型,如“ObjectId”、“Min key”、“UUID”或“MD5”(我认为这些类型是MongoDB所需要的)。这些类型与JSON不兼容。这意味着,当您将对象从BSON转换为JSON时,某些类型信息可能会丢失,但当然只有当这些特殊类型位于BSON源中时才会丢失。在单个服务中同时使用JSON和BSON可能是一个缺点

    MessagePack被设计成透明地从JSON转换为JSON

  • MessagePack比BSON小

    MessagePack的格式比BSON更详细。因此,MessagePack可以序列化比BSON更小的对象

    例如,一个简单的映射{“a”:1,“b”:2}使用MessagePack以7个字节序列化,而BSON使用19个字节

  • BSON支持就地更新

    使用BSON,您可以修改存储对象的一部分,而无需重新序列化整个对象。让我们假设一个映射{“a”:1,“b”:2}存储在一个文件中,并且您希望将“a”的值从1更新到2000

    对于MessagePack,1只使用1个字节,而2000使用3个字节。所以“b”必须向后移动2个字节,而“b”不被修改

    对于BSON,1和2000都使用5个字节。由于这种冗长,您不必移动“b”

  • MessagePack具有RPC

    MessagePack、协议缓冲区、Thrift和Avro支持RPC。但BSON没有

  • 这些差异意味着MessagePack最初是为网络通信而设计的,而BSON是为存储而设计的

    实现和API设计


    <> MessagePack >具有类型检查API(java、C++和d)< /p> MessagePack支持静态类型

    与JSON或BSON一起使用的动态类型对于Ruby、Python或JavaScript等动态语言非常有用。但是对于静态语言来说很麻烦。你必须写无聊的类型检查代码

    MessagePack提供类型检查API。它将动态类型化对象转换为静态类型化对象。下面是一个简单的示例(C++):

    #包括
    类myclass{
    私人:
    std::字符串str;
    std::vec;
    公众:
    //此宏允许对此类进行序列化/反序列化
    MSGPACK_DEFINE(str,vec);
    };
    内部主(空){
    //连载
    myclass m1=。。。;
    msgpack::sbuffer缓冲区;
    msgpack::pack(&缓冲区,m1);
    //反序列化
    msgpack::解包结果;
    msgpack::解包(&result,buffer.data(),buffer.size());
    //您将获得动态类型化的对象
    msgpack::object obj=result.get();
    //将其转换为静态类型的对象
    myclass m2=obj.as();
    }
    
  • MessagePack具有IDL

    它与类型检查API有关,MessagePack支持IDL。(规格可从以下网址获得:)

    协议缓冲区和节俭需要IDL(不支持动态类型)并提供更成熟的IDL实现

  • <> MessagePack >具有流API(Ruby、Python、java、C++、…)

    MessagePack支持流式反序列化程序。此功能对于网络通信非常有用。下面是一个示例(Ruby):

    需要“msgpack”
    #将对象写入标准输出
    $stdout.write[1,2,3].\u msgpack
    $stdout.write[1,2,3].\u msgpack
    #使用流式反序列化器从stdin读取对象
    unpacker=MessagePack::unpacker.new($stdin)
    #使用迭代器
    解包器。每个{对象|
    p obj
    }
    
    快速测试表明,缩小的JSON反序列化速度比二进制MessagePack快。在测试中,Article.json是550kb的小型json,Article.mpack是它的420kb MP版本。当然,这可能是一个实施问题

    信息包:

    //test_mp.js
    var msg = require('msgpack');
    var fs = require('fs');
    
    var article = fs.readFileSync('Article.mpack');
    
    for (var i = 0; i < 10000; i++) {
        msg.unpack(article);    
    }
    
    所以节省了空间,但速度更快?没有

    测试版本:

    Anarki:Downloads oleksii$ node --version
    v0.8.12
    Anarki:Downloads oleksii$ npm list msgpack
    /Users/oleksii
    └── msgpack@0.1.7  
    

    我认为非常重要的一点是,这取决于客户机/服务器环境的外观

    如果在不检查的情况下多次传递字节,例如使用消息队列系统或将日志项流式传输到磁盘,那么您可能更喜欢使用二进制编码来强调紧凑的大小。否则,这将是不同环境下的具体问题

    有些环境可以与msgpack/protobuf进行非常快速的序列化和反序列化,其他环境则不然。一般来说,语言/环境的级别越低,二进制序列化的效果就越好。在更高级的语言(node.js、.Net、JVM)中,您经常会看到JSON序列化实际上更快。然后问题就变成了,您的网络开销是否比内存/cpu受到更多或更少的限制

    关于msgpack vs bson vs协议缓冲区。。。msgpack是组中最小的字节,协议缓冲区大致相同。BSON定义了比其他两种更广泛的本机类型,并且可能更适合您的对象模型,但这会使它更加冗长。协议缓冲区的优点是被设计成流。。。这使得它成为二进制传输/存储的更自然的格式
    Anarki:Downloads oleksii$ time node test_mp.js 
    
    real    2m45.042s
    user    2m44.662s
    sys     0m2.034s
    
    Anarki:Downloads oleksii$ time node test_json.js 
    
    real    2m15.497s
    user    2m15.458s
    sys     0m0.824s
    
    Anarki:Downloads oleksii$ node --version
    v0.8.12
    Anarki:Downloads oleksii$ npm list msgpack
    /Users/oleksii
    └── msgpack@0.1.7  
    
    document    ::=     int32 e_list
    
    BSON writer: 2296 ms (243487 bytes)
    BSON reader: 435 ms
    MESSAGEPACK writer: 5472 ms (243510 bytes)
    MESSAGEPACK reader: 1364 ms
    
        public class TestData
        {
            public byte[] buffer;
            public bool foobar;
            public int x, y, w, h;
        }
    
        static void Main(string[] args)
        {
            try
            {
                int loop = 10000;
    
                var buffer = new TestData();
                TestData data2;
                byte[] data = null;
                int val = 0, val2 = 0, val3 = 0;
    
                buffer.buffer = new byte[243432];
    
                var sw = new Stopwatch();
    
                sw.Start();
                for (int i = 0; i < loop; i++)
                {
                    data = SerializeBson(buffer);
                    val2 = data.Length;
                }
    
                var rc1 = sw.ElapsedMilliseconds;
    
                sw.Restart();
                for (int i = 0; i < loop; i++)
                {
                    data2 = DeserializeBson(data);
                    val += data2.buffer[0];
                }
                var rc2 = sw.ElapsedMilliseconds;
    
                sw.Restart();
                for (int i = 0; i < loop; i++)
                {
                    data = SerializeMP(buffer);
                    val3 = data.Length;
                    val += data[0];
                }
    
                var rc3 = sw.ElapsedMilliseconds;
    
                sw.Restart();
                for (int i = 0; i < loop; i++)
                {
                    data2 = DeserializeMP(data);
                    val += data2.buffer[0];
                }
                var rc4 = sw.ElapsedMilliseconds;
    
                Console.WriteLine("Results:", val);
                Console.WriteLine("BSON writer: {0} ms ({1} bytes)", rc1, val2);
                Console.WriteLine("BSON reader: {0} ms", rc2);
                Console.WriteLine("MESSAGEPACK writer: {0} ms ({1} bytes)", rc3, val3);
                Console.WriteLine("MESSAGEPACK reader: {0} ms", rc4);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
    
            Console.ReadLine();
        }
    
        static private byte[] SerializeBson(TestData data)
        {
            var ms = new MemoryStream();
    
            using (var writer = new Newtonsoft.Json.Bson.BsonWriter(ms))
            {
                var s = new Newtonsoft.Json.JsonSerializer();
                s.Serialize(writer, data);
                return ms.ToArray();
            }
        }
    
        static private TestData DeserializeBson(byte[] data)
        {
            var ms = new MemoryStream(data);
    
            using (var reader = new Newtonsoft.Json.Bson.BsonReader(ms))
            {
                var s = new Newtonsoft.Json.JsonSerializer();
                return s.Deserialize<TestData>(reader);
            }
        }
    
        static private byte[] SerializeMP(TestData data)
        {
            return MessagePackSerializer.Typeless.Serialize(data);
        }
    
        static private TestData DeserializeMP(byte[] data)
        {
            return (TestData)MessagePackSerializer.Typeless.Deserialize(data);
        }