zoukankan      html  css  js  c++  java
  • [转]序列化悍将Protobuf-Net,入门动手实录

    最近在研究web api 2,看了一篇文章,讲解如何提升性能的

    在序列化速度的跑分中,Protobuf一骑绝尘,序列化速度快,性能强,体积小,所以打算了解下这个利器

    1:安装篇

    谷歌官方没有提供.net的实现,所以在nuget上找了一个移植的

    Nuget里搜索Protobuf-net,下载,自动添加到项目中

    2:定义数据结构 

    复制代码
    using ProtoBuf;
    
    namespace ConsoleApplication1
    {
        [ProtoContract]
        class Person
        {
            [ProtoMember(1)]
            public int Id { get; set; }
            [ProtoMember(2)]
            public string Name { get; set; }
            [ProtoMember(3)]
            public Address Address { get; set; }
        }
        [ProtoContract]
        class Address
        {
            [ProtoMember(1)]
            public string Line1 { get; set; }
            [ProtoMember(2)]
            public string Line2 { get; set; }
        }
    }
    复制代码

      

    3:封装简单操作类

    按照作者使用习惯,简单提供了一个Helper类

    复制代码
    using System.IO;
    using System.Text;
    using ProtoBuf;
    
    namespace ConsoleApplication1
    {
       public class ProtobufHelper
        {
           /// <summary>
           /// 序列化
           /// </summary>
           /// <typeparam name="T"></typeparam>
           /// <param name="t"></param>
           /// <returns></returns>
           public static string Serialize<T>(T t)
           {
               using (MemoryStream ms = new MemoryStream())
               {
                   Serializer.Serialize<T>(ms, t);
                   return Encoding.UTF8.GetString(ms.ToArray());
               }
           }
    
           /// <summary>
           /// 反序列化
           /// </summary>
           /// <typeparam name="T"></typeparam>
           /// <param name="content"></param>
           /// <returns></returns>
           public static T DeSerialize<T>(string content)
           {
               using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(content)))
               {
                   T t = Serializer.Deserialize<T>(ms);
                   return t;
               }
           }
        }
    }
    复制代码

    4:操作体验

    代码很简单,就不分开贴了

    复制代码
    using System;
    using System.Collections.Generic;
    using System.IO;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                var p1 = new Person
                {
                    Id = 1,
                    Name = "八百里开外",
                    Address = new Address
                    {
                        Line1 = "Line1",
                        Line2 = "Line2"
                    }
                };
    
                var p2 = new Person
                {
                    Id = 2,
                    Name = "一枪",
                    Address = new Address
                    {
                        Line1 = "Flat Line1",
                        Line2 = "Flat Line2"
                    }
                };
    
                List<Person> pSource = new List<Person>() { p1, p2 };
    
                string content = ProtobufHelper.Serialize<List<Person>>(pSource);
    
                Console.Write(content);
                //写入文件
                File.WriteAllText("D://hello.txt", content);
                 
    
    
                Console.WriteLine("
    ****解析部分*****");
    
                List<Person> pResult = ProtobufHelper.DeSerialize<List<Person>>(content);
    
    
                foreach (Person p in pResult)
                {
                    Console.WriteLine(p.Name);
                }
    
                Console.Read();
            }
        }
    }
    复制代码

    控制台运行结果

    同样的数据,和Json所占用空间对比,高下立判

    后记

    protobuf虽然有千般好,但是我们是在 web api上使用的,前台js解析不了Protobuf,所以只能用Json咯~!

    StackService虽然Github上有2K多个Star,但是收费的。。同样的事情web api 2也能做到,所以也略过它。

    最终作者选择了跑分测试里面的第二名Jil  https://github.com/kevin-montrose/Jil


    1. With very minimal annotation on the class level

    [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] // only required on the class level
    class PersonEntity
    {
       public string FirstName { get; set; }
       public string LastName { get; set; }
    }

    2. Without any annotation (using RuntimeTypeModel)

    static void InitializeProtobufRunTime()
    {
        var assembly = Assembly.GetAssembly(typeof(PlainEntities.PersonEntity));
        var types = assembly.GetTypes();
        foreach (var t in types.Where(x => x.Namespace.Contains("PlainEntities")))
        {
            Console.WriteLine("Processing {0}", t.FullName);
            var meta = RuntimeTypeModel.Default.Add(t, false);
            var index = 1;
    
            // find any derived class for the entity
            foreach (var d in types.Where(x => x.IsSubclassOf(t)))
            {
                var i = index++;
                Console.WriteLine("	Subtype: {0} - #{1}", d.Name, i);
                meta.AddSubType(i, d);
            }
    
            // then add the properties
            foreach (var p in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Where(x => x.GetSetMethod() != null))
            {
                var i = index++;
                Console.WriteLine("	Property: {0} - #{1}", p.Name, i);
                meta.AddField(i, p.Name);
            }
        }
    }

    And both the above works quite well without any performance differences.


    ------------------
    TestBinaryEntities
    ------------------
    Process: 100000 items, MemorySize: 7400705, Completed in: 3877 ms, Serialization took: 676 ms, Deserialization took: 2948 ms

    ----------------------------------
    TestProtobufFullyAnnotatedEntities
    ----------------------------------
    Process: 100000 items, MemorySize: 3983490, Completed in: 682 ms, Serialization took: 164 ms, Deserialization took: 253 ms

    -------------------------------------
    TestProtobufImplicitAnnotatedEntities
    -------------------------------------
    Process: 100000 items, MemorySize: 3983490, Completed in: 595 ms, Serialization took: 104 ms, Deserialization took: 210 ms

    -------------------------------
    TestProtobufRuntimeRegistration
    -------------------------------
    Processing ProtobufTestConsole.PlainEntities.BaseEntity
    Subtype: PersonEntity - #1
    Property: Id - #2
    Property: Gender - #3
    Processing ProtobufTestConsole.PlainEntities.PersonEntity
    Property: FirstName - #1
    Property: LastName - #2
    Property: Age - #3
    Process: 100000 items, MemorySize: 4083490, Completed in: 646 ms, Serialization took: 113 ms, Deserialization took: 232 ms

    Looking forward to get this in :)

    Also attached the sample project for reference

  • 相关阅读:
    TSINGSEE青犀视频编译中通过Golang代码修改Linux服务的ulimit的实现
    为什么说全球疫情的刺激,加快了AI视频智能分析技术的需求?
    EasyPlayer.JS播放录像报错视频文件损坏且播放终止怎么处理?
    TSINGSEE青犀视频开发AI智能分析采用c++中文编码出现乱码问题是由什么导致的
    EasyPlayerJS开发环境出现错误信息并且不展示播放器问题优化
    EasyNVR开发中VLC Player如何将日志输入到文件中以及设置以TCP方式拉取RTSP流
    车牌识别在智慧交通中的重要作用
    树型结构数据,求某结点的所有父结点的自定义函数
    一条有意思的SQL语句分析
    树形数据显示SQL示例代码(在ms sql 2000 DBMS中调试通过)
  • 原文地址:https://www.cnblogs.com/zhahost/p/5813627.html
Copyright © 2011-2022 走看看