2018-8-10-C#-配置文件存储-各种序列化算法性能比较
| title | author | date | CreateTime | categories | 
|---|---|---|---|---|
| C# 配置文件存储 各种序列化算法性能比较 | lindexi | 2018-08-10 19:16:52 +0800 | 2018-06-15 12:16:10 +0800 | C# | 
本文比较多个方式进行配置文件的存储,对比各个不同算法的读写性能。
在应用软件启动的时候,需要读取配置文件,但是启动的性能很重要,所以需要有一个很快的读取配置文件的方法。
如果你不想看过程,那么请看拖动滚动条
本文将会比较三个世界上最好的序列化算法,一个是 json 、一个是 ProtoBuf 、一个是 wire
原来我的软件在启动的时候是需要读取很多个文件,因为每个模块的配置都不同,所有模块的配置都是模块自己查找配置文件读取,然而大家都知道,在机械硬盘,随机读取文件的性能很差。现在虽然很多用户都是使用固态硬盘,但是对于启动性能优化,还是要尽量减少在软件启动过程的读取文件。
我询问了奎爷,他是一位强大的程序员,他告诉我,谷歌浏览器把很多零碎的文件,如历史记录和密码都压缩为一个文件,这样的启动时候,顺序读取性能很快,所以浏览器才可以快速启动。
于是我就开始了准备把所有的模块的配置文件合为一个,在合并的时候需要做序列化,因为存在很多模块都是使用自己实现的方式进行序列化。
下面就是我进行对比各个算法的性能。
需要注意,在软件启动的时候,还需要计算 dll 加载的性能,也就是如果有一个dll可以提高序列化性能,但是这个 dll 加载性能很差,也是不能使用这个dll的。
定义
先定义一个简单的类,这个类用来存放数据,只有 key-value 的数据
[ProtoContract]
[Serializable]
public class Foo
{
[ProtoMember(1)]
public Dictionary<string, string> CurmobeKallbu { set; get; }
}
在启动之前就需要读取这个文件作为配置,所以需要找到一个很快的方法从文件读取,然后反序列化。
为了方便序列化,我写了一个方法Foo.BegaymouniWaloujijou用来创建 1000 个随机的 key-value 为数据。因为代码很多,我就不写了,下面就是函数的定义,需要大家写入随机的值
public static Foo BegaymouniWaloujijou()
{
return new Foo()
{
CurmobeKallbu = new Dictionary<string, string>()
{
// 这里写入随机的值
}
};
}
json
首先是使用最有名的 json 来进行序列化,安装 Nuget 第一个,点击管理nuget,然后点击浏览,现在看到的第一个是不是 json 库?如果不是,那么说明本文已经过期
在看本文的时候,如果要运行本文的代码,需要先在自己的 E 盘创建一个叫回收站的文件夹。因为我在代码会对这个文件夹写入。
            var fileInfo = new FileInfo(@"E:\回收站\xx5");
            if (!fileInfo.Exists)
            {
                var foo = Foo.BegaymouniWaloujijou();
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                using (var stream = new StreamWriter(fileInfo.OpenWrite()))
                {
                    var str = JsonConvert.SerializeObject(foo, Formatting.Indented);
                    stream.Write(str);
                }
                stopwatch.Stop();
                Console.WriteLine("写入" + stopwatch.ElapsedMilliseconds);
            }
            else
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                var stream = fileInfo.OpenText();
                using (stream)
                {
                    var foo = JsonConvert.DeserializeObject<Foo>(stream.ReadToEnd());
                }
                stopwatch.Stop();
                Console.WriteLine("读取时间" + stopwatch.ElapsedMilliseconds);
                fileInfo.Delete();
            }
上面的代码很简单,就是使用这个方式保存
那么性能怎样?请看下面
读取 写入
170 188
161 150
191 168
166 164
230 156
数据的单位是毫秒,平均时间是读取 183.6 毫秒,写入165.2毫秒
ProtoBuf
这是 谷歌的一个库,我安装了 protobuf-net ,然后进行序列化
var fileInfo = new FileInfo(@"E:\回收站\xx2");
if (!fileInfo.Exists)
{
var foo = Foo.BegaymouniWaloujijou(); var stopwatch = new Stopwatch(); stopwatch.Start(); var stream = fileInfo.OpenWrite(); using (stream)
{
Serializer.Serialize(stream, foo);
} stopwatch.Stop(); Console.WriteLine("写入" + stopwatch.ElapsedMilliseconds);
}
else
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var stream = fileInfo.OpenRead();
using (stream)
{
stream.Seek(0, SeekOrigin.Begin); var foo = Serializer.Deserialize<Foo>(stream);
} stopwatch.Stop();
Console.WriteLine("读取时间" + stopwatch.ElapsedMilliseconds);
fileInfo.Delete();
}
我尝试在 ssd 和 机械硬盘读写,比较两个的性能
下面是在 ssd 的读写性能,平均时间是读取 91.8 毫秒,写入 119.4 毫秒
读取 写入
90 108
84 115
93 142
80 109
112 123
我尝试在机械硬盘读写,平均时间是读取104.4毫秒,写入140.2毫秒
读取 写入
95 127
115 163
107 168
98 128
107 115
wire
这是传说中最快的序列化库,我安装了 Wire 然后使用下面的代码,运行 5 次计算读写时间
          var fileInfo = new FileInfo(@"E:\回收站\xx3");
            if (!fileInfo.Exists)
            {
                var foo = Foo.BegaymouniWaloujijou();
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                var stream = fileInfo.OpenWrite();
                using (stream)
                {
                    var serializer = new Wire.Serializer();
                    serializer.Serialize(foo, stream);
                }
                stopwatch.Stop();
                Console.WriteLine("写入" + stopwatch.ElapsedMilliseconds);
            }
            else
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                var stream = fileInfo.OpenRead();
                using (stream)
                {
                    var serializer = new Wire.Serializer();
                    var foo = serializer.Deserialize<Foo>(stream);
                }
                stopwatch.Stop();
                Console.WriteLine("读取时间" + stopwatch.ElapsedMilliseconds);
                fileInfo.Delete();
            }
虽然小伙伴说他是最快的,但是在我的设备,平均读取125.8毫秒,写入101.2毫秒
读取 写入
109 104
106 94
111 92
190 90
113 126
自己写的
最后我尝试自己写了简单的序列化,因为存放的信息是key-value,我可以控制包含的字符串都是不带换行,也就是我可以一行放 value 一行放关键字。
var fileInfo = new FileInfo(@"E:\回收站\xx7");
if (!fileInfo.Exists)
{
var foo = Foo.BegaymouniWaloujijou(); var stopwatch = new Stopwatch(); stopwatch.Start(); using (var stream = new StreamWriter(fileInfo.OpenWrite()))
{
foreach (var temp in foo.CurmobeKallbu)
{
stream.WriteLine(temp.Key);
stream.WriteLine(temp.Value);
}
} stopwatch.Stop(); Console.WriteLine("写入" + stopwatch.ElapsedMilliseconds);
}
else
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var stream = fileInfo.OpenText();
using (stream)
{
var str = stream.ReadToEnd().Split('\n');
var foo = new Foo();
foo.CurmobeKallbu = new Dictionary<string, string>(str.Length / 2);
string key = null;
foreach (var temp in str)
{
if (key == null)
{
key = temp;
}
else
{
foo.CurmobeKallbu.Add(key, temp);
key = null;
}
}
} stopwatch.Stop();
Console.WriteLine("读取时间" + stopwatch.ElapsedMilliseconds);
fileInfo.Delete();
}
我发现在 ssd 和在机械硬盘读写性能几乎没有相差,有时候相同程序在 ssd 运行的时间比在机械硬盘多。在我测试了自己写的程序才知道,最多的时间在序列化,读取文件的时间反而可以被忽略。使用自己写的序列化读取1毫秒,写入7.2毫秒,所以这么简单的配置文件还是自己做序列化比较快。
读取 写入
1 6
1 8
1 8
1 5
1 9
建议
在软件启动的时候,还有一个读取文件是加载库,如果我使用了第三方的 dll ,那么在启动的时候我就需要加载这个 dll ,但是我读取的配置文件只有不到 100 k 但是我加载的几个库都是很大。加载库的时间已经足够我自己写的序列化读取完成,需要知道,在启动程序的时候不是把所有程序的库都加载,只有在用到的时候才去读取库,读取库也是需要时间,所以程序启动的时候尽量不要引用不相关的库。
所以在启动的过程如果需要读取配置文件,还是使用自己写序列化,而且要求自己写的配置文件很稳定,不要在启动的时候出现异常。
自己写配置文件可以在一个线程进行读取,然后把整个程序所有在启动过程使用配置文件的地方都删除,只有软件启动的过程读取的文件只有很少的几个,最好是一个,这样才能保证软件启动的性能。
代码:C# 配置文件存储 各种序列化算法性能比较 程序1.1-CSDN下载
如果没有积分需要代码请联系我
2018-8-10-C#-配置文件存储-各种序列化算法性能比较的更多相关文章
- C# 配置文件存储 各种序列化算法性能比较
		本文比较多个方式进行配置文件的存储,对比各个不同算法的读写性能. 在应用软件启动的时候,需要读取配置文件,但是启动的性能很重要,所以需要有一个很快的读取配置文件的方法. 如果你不想看过程,那么请看拖动 ... 
- 新手C#SQL Server使用记录2018.08.10
		主键(PrimaryKey):主键就是每个数据行(记录)的唯一标识,不会有重复值的列(字段)才能当做主键.一个表可以没有主键,但是这样会很难处理表,因此一般情况表都要设置主键. 主键有两张选用策略,分 ... 
- 01 mybatis框架整体概况(2018.7.10)-
		01 mybatis框架整体概况(2018.7.10)- F:\廖雪峰 JavaEE 企业级分布式高级架构师课程\廖雪峰JavaEE一期\第一课(2018.7.10) maven用的是3.39的版本 ... 
- Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据
		本来这篇文章在昨天晚上就能发布的,悲剧的是写了两三千字的文章居然没保存,结果我懵逼了.今天重新来写这篇文章.今天我们就一起来探讨下如何重写Ocelot配置文件的存储方式以及获取方式. 作者:依乐祝 原 ... 
- 申请Office 365一年免费的开发者账号攻略(2018年10月份版本)
		要进行Office 365开发,当然需要有完整的Office 365环境才可以.为了便于广大开发人员快速地启动这项工作,微软官方给所有开发人员提供了免费的一年开发者账号 那么如何申请Office ... 
- Docker Swarm 配置文件存储
		Docker Swarm 配置文件存储 config:宿主级容器服务配置文件单独保存到docker中存储调用. 环境: 系统:Centos 7.4 x64 应用版本:Docker 18.09.0 管理 ... 
- IntelliJ IDEA 最新激活码(截止到2018年10月14日)
		IntelliJ IDEA 注册码: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUlXU1dEIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYX ... 
- 北京化工大学2018年10月程序设计竞赛部分题解(A,C,E,H)
		目录 北京化工大学2018年10月程序设计竞赛部分题解(A,C,E,H) 竞赛事件相关 竞赛链接 竞赛题目 总结 北京化工大学2018年10月程序设计竞赛部分题解(A,C,E,H) 竞赛事件相关 竞赛 ... 
- 富士康的盈利秒杀99%的A股公司:3星|《三联生活周刊》2018年10期
		三联生活周刊·最美的数学:天才为何成群到来(2018年10期) 本期专题是数学和成都,我都跳过去没看.其他内容也还有点意思. 总体评价3星. 以下是本期一些内容的摘抄,#号后面是kindle电子版中的 ... 
随机推荐
- 微信小程序のmina架构
- Linux账号管理与ALC权限设定(一)
			UID 与 GID UID用户的编号 GID 用户群组的编号 账号登录时,有一个对应的文本来记录某个账户的UID与GID.然后获得这个UID去对应的密码文本中,取得密码进行比对,然后登陆. 保 ... 
- Oracle实现主键自增的几种方式
			数据库作为一个系统的核心,数据库设计的1NF就是一个表结构必须有唯一约束也就是主键,Oracle数据库本身没有自增机制,不像MySQL直接使用关键字AUTO_INCREMENT自动加一,所以需要我们去 ... 
- es5-class
			1. 通过class定义类/实现类的继承2. 在类中通过constructor定义构造方法3. 通过new来创建类的实例4. 通过extends来实现类的继承5. 通过super调用父类的构造方法6. ... 
- 【JavaWeb项目】一个众筹网站的开发(八)后台页面详细设置
			一.user.jsp改造 删除引入菜单 抽取导航栏 nav-bar.jsp,删除引入导航栏 删除引入main.jsp的到好烂 数据库里添加url 报错,url不对 没有/ url正确 action=& ... 
- Java开发常见基础题大全
			1.&和&&的区别? &:逻辑与(and),运算符两边的表达式均为true时,整个结果才为true. &&:短路与,如果第一个表达式为false时,第二 ... 
- Java IO之处理流
			一.处理流: 增强功能,提供性能,在节点流之上. 二.节点流与处理流的关系 节点流(字节流.字符流)处于IO操作的第一线,所有操作必须通过它们进行: 处理流可以对其他流进行处理(提高效率或操作灵活性) ... 
- 使用Vue和djangoframwork完成登录页面构建 001
			使用Vue和djangoframwork完成登录页面构建 001 环境的搭建 首先,我在我的电脑的F盘创建了一个文件夹 forNote,进入到这个文件夹中 F:\forNote> vue环境的搭 ... 
- 把sublime添加到右键快捷菜单
			方法一: 新建sublime_addright.reg文件 编辑后双击打开就OK 括号内是sublime安装路径:使用的时候去掉括号 open sublimeText3 是提示文字 Windows R ... 
- Android中的Service 与 Thread 的区别
			很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下. 1). Thread:Thre ... 
