.net BinaryFormatter序列化对象慢的原因

    最近在做组件对象写入流的优化,因此对一些.net下序列化组件做了一些测试,分别针对ProtoBuf.net 和.net自带的BinaryFormatter进行了分析.从测试的结果来看BinaryFormatter的性能和ProtoBuf.net的性能足足相差了10倍。为什么差这么远呢,如果紧紧从运行时间来看可能以为BinaryFormatter一定是使用反射什么的,所以导致结果这么慢。为了更清楚的了解具体情况于是对两者的测试代码进行了一个内存分析.

ProtoBuf.net的测试代码

        public void PB(int count)
        {
            TestPB obj = new TestPB();
            obj.Email = "henryfan@test.com";
            obj.FirstName = "henry";
            obj.LastName = "fan";
            obj.ID = 3456;
            obj.Phone = "13418888121";
            obj.Type = 67;
            System.IO.MemoryStream stream = new System.IO.MemoryStream(265);
            stream.Position = 0;
            ProtoBuf.Serializer.Serialize<TestPB>(stream, obj);
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Reset();
            sw.Start();
            for (int i = 0; i < count; i++)
            {
                stream.Position = 0;
                ProtoBuf.Serializer.Serialize<TestPB>(stream, obj);
            }
            sw.Stop();
            Console.WriteLine("ProtoBuf Serialize Objects{0} Time:{1}", count, sw.Elapsed.TotalMilliseconds);
        }

BinaryFormatter的测试代码

        public void DotNet(int count)
        {

            TestDotNet obj = new TestDotNet();
            obj.Email = "henryfan@test.com";
            obj.FirstName = "henry";
            obj.LastName = "fan";
            obj.ID = 3456;
            obj.Phone = "13418888121";
            obj.Type = 67;
            System.IO.MemoryStream stream = new System.IO.MemoryStream(256);
            BinaryFormatter bf = new BinaryFormatter();
            stream.Position = 0;
            bf.Serialize(stream, obj);
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Reset();
            sw.Start();
            for (int i = 0; i < count; i++)
            {
                stream.Position = 0;
                bf.Serialize(stream, obj);
            }
            sw.Stop();
            Console.WriteLine("BinaryFormatter Serialize Objects{0} Time:{1}", count,sw.Elapsed.TotalMilliseconds);
        }

通过内存分析针对上面代码进行100000次的序列化对象查看其内存开销的情况

ProtoBuf.net 的内存使用情况

名称非独占分配数独占分配数非独占字节数独占字节数非独占分配数百分比
+ProtoBuf.ProtoWriter100,001100,0016,000,0606,000,06024.44
+ProtoBuf.NetObjectCache100,001100,0012,400,0242,400,02424.44
+ProtoBuf.Meta.RuntimeTypeModel.TypeFinder200,002200,0022,400,0242,400,02448.88
+System.Byte[]1,1991,1992,111,0602,111,0600.29
+System.String69769732,41832,4180.17
+System.Char[]444425,38225,3820.01
+System.Object[]35035020,30020,3000.09
+System.Collections.Generic.List`158958914,13614,1360.14
+System.Reflection.Emit.OpCode2262269,9449,9440.06
+System.Reflection.MethodInfo[]2562569,0129,0120.06
+System.Reflection.RuntimeMethodInfo1231236,8886,8880.03
+System.Collections.ArrayList2592596,2166,2160.06

BinaryFormatter的内存使用情况

名称非独占分配数独占分配数非独占字节数独占字节数非独占分配数百分比
+System.Collections.Hashtable.bucket[]500,008500,00872,001,65672,001,6568.77
+System.Object[]600,012600,01239,204,63639,204,63610.52
+System.Byte[]201,074201,07431,699,20531,699,2053.53
+System.Collections.Hashtable500,008500,00828,000,44828,000,4488.77
+System.Runtime.Serialization.Formatters.Binary.NameInfo400,004400,00419,200,19219,200,1927.01
+System.String100,078100,07819,005,03619,005,0361.75
+System.Int64[]100,001100,00117,200,17217,200,1721.75
+System.Runtime.Serialization.Formatters.Binary.ObjectWriter100,001100,00110,400,10410,400,1041.75
+System.Runtime.Serialization.Formatters.Binary.__BinaryWriter100,001100,00110,000,10010,000,1001.75
+System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo100,001100,0016,800,0686,800,0681.75
+System.Runtime.Serialization.Formatters.Binary.SerStack200,002200,0024,800,0484,800,0483.51
+System.Runtime.Serialization.Formatters.Binary.BinaryObjectWithMapTyped100,001100,0014,400,0444,400,0441.75

从上面两个内存分析结果来看就一目了然了,ProtoBuf.net在序列化的过程中紧紧只开销了13MB左右的内存,所创建对象的总数大概在400000个左右;反观BinaryFormatter在序列化过程确使用了300多MB的内存,创建对象总数接近6000000个。紧紧是对象的创建对象的数量就已经是ProtoBuf.net 10倍,因此效率慢就是正常的事。MS为什么这样做这个就不得而知了,明明可以做得很好的,但确并没这样做……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值