title author date CreateTime categories
C# 程序集数量对软件启动性能的影响
lindexi
2019-08-31 16:55:58 +0800
2018-10-17 9:24:3 +0800
C# 性能测试

本文通过很多的数据测试分析在一个项目引用很多个外部项目和将外部项目的类合并到一个项目之间的启动性能的不同。
通过分析知道了如果一个项目引用了很多项目,而且在启动过程会全部调用这些项目,这时的软件性能会比将这些项目的代码合并到一个项目的慢很多
本文的数据为 预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv 提供

最近在做一个编译器相关的项目,这个项目是将多个库作为源代码的 nuget 包,这样就可以在开发的时候是使用多个不同的项目,避免项目之间耦合。编译的时候将多个项目编译为 一个 dll 提高了软件启动性能。而且通过源代码包的引用方式可以极大避免了在不同的平台迁移的难度,只要是代码兼容的,甚至代码部分不兼容可以使用宏的方式在不同的平台使用不同的代码。

为了告诉大家这个项目的用处,于是本文就使用代码创建的方式创建了很多代码,通过对比这些代码的运行可以知道将类分在多个项目,和将类放在一个项目在运行过程的性能

我通过创建两个不同的工程,第一个工程是包含一个项目,这个项目里有 5000 个空类,在启动之后会创建这 5000 个类中的 1000 个类。

第二个工程包括了 1000 个项目,每个项目有 5 个空类,这里的空类和前面项目的空类是一样的创建方法。然后再添加一个启动项目,这个启动项目引用了前面的 1000 个项目,在启动之后会创建 1000 个项目中每个项目的一个类,也就是创建了 1000 个类,只是每个类都在不同的项目。

经过了很长时间的编译,我运行了一个项目5000个类的项目,初次运行时间是 54 ms ,接下来两次运行时间分别是 52 ms 和 53 ms 时间很短。

然后运行 1000 个项目,一个项目 5 个类的项目,冷启动时间是 15246 毫秒,之后的运行时间如下

第二次 580 ms

第三次 552 ms

第四次 546 ms

第五次 563 ms

第六次 568 ms

第七次 569 ms

下面表格是对比两个工程运行时间

工程 冷启动 第二次 第三次
一个项目5000个类 54 ms 52 ms 53 ms
1000个项目,一个项目5个类 15246 ms 580 ms 552 ms

从上面表格可以看到,冷启动的性能差是 280 倍,此后的运行的性能差大概是 10 倍

然后我还测试了 1000 个项目,一个项目 1000 个类的运行时间,冷启动 22993 毫秒,热启动三次的数据是 885 毫秒,871 毫秒和 861 毫秒

测试项目的代码可以从 csdn 下载,如果没有积分请发邮件给我。如果觉得上面的数据很诡异,请自己运行一下编译一下

一个项目5000 个类-CSDN下载

在 1000 个项目,一个项目里有 5 个类-CSDN下载

创建测试项目的代码请看下面

创建一个项目这个项目里有 5000 个类,在启动之后调用这 5000 个类里的 1000 个

{% raw %}

        private static void LownearkeajooSasouStegisti()
{
var saryawpirmiGerekipoNehiti = new DirectoryInfo("MayairJowya"); saryawpirmiGerekipoNehiti.Create(); var fawniSorhaHereni = new List<string>(); var deleeTacarirouWulall = new WhairchooHerdo(); for (int gupoudigorKihirkercou = 0; gupoudigorKihirkercou < 1000; gupoudigorKihirkercou++)
{
var teaJawtu = deleeTacarirouWulall.LemgeDowbovou(); for (int mirxarJeredrairsear = 0; mirxarJeredrairsear < 5; mirxarJeredrairsear++)
{
var cicirRarsonisallJearwelxe = deleeTacarirouWulall.LemgeDowbovou(); var facoSaijeesereniXaimow = $@"
using System;
using System.Collections.Generic;
using System.Text; namespace {teaJawtu}
{{
public class {cicirRarsonisallJearwelxe}
{{
public string Foo {{ get; set; }}
}}
}}";
if (mirxarJeredrairsear == 0)
{
fawniSorhaHereni.Add(teaJawtu + "." + cicirRarsonisallJearwelxe);
} File.WriteAllText(
Path.Combine(saryawpirmiGerekipoNehiti.FullName, cicirRarsonisallJearwelxe + ".cs"),
facoSaijeesereniXaimow);
}
} var jawjearPalfokallPuwuTearbourer = new StringBuilder(); jawjearPalfokallPuwuTearbourer.Append(@"<Project Sdk=""Microsoft.NET.Sdk""> <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> <ItemGroup>
"); jawjearPalfokallPuwuTearbourer.Append(@" </ItemGroup> </Project>"); File.WriteAllText(Path.Combine(saryawpirmiGerekipoNehiti.FullName, "TirkalltremceFalgawCouwabupu.csproj"),
jawjearPalfokallPuwuTearbourer.ToString()); jawjearPalfokallPuwuTearbourer.Clear(); var cepepiSowneKorrer = @"using System;
using System.Diagnostics; namespace CouwharjeMerball
{
class Program
{
static void Main(string[] args)
{
var dafuWhayroubaXouma = new Stopwatch();
dafuWhayroubaXouma.Start();
var kawgeDeesearsofas = new KawgeDeesearsofas();
kawgeDeesearsofas.LurtrajaboPearbubirXinene();
dafuWhayroubaXouma.Stop();
Console.WriteLine(dafuWhayroubaXouma.ElapsedMilliseconds);
}
}
}
";
File.WriteAllText(Path.Combine(saryawpirmiGerekipoNehiti.FullName, "Program.cs"), cepepiSowneKorrer); jawjearPalfokallPuwuTearbourer.Append(@"namespace CouwharjeMerball
{
class KawgeDeesearsofas
{
public void LurtrajaboPearbubirXinene()
{
"); foreach (var ferosarTadir in fawniSorhaHereni)
{
jawjearPalfokallPuwuTearbourer.Append(" new " + ferosarTadir + "();");
jawjearPalfokallPuwuTearbourer.Append("\r\n");
} jawjearPalfokallPuwuTearbourer.Append(@" }
}
}"); File.WriteAllText(Path.Combine(saryawpirmiGerekipoNehiti.FullName, "KawgeDeesearsofas.cs"),
jawjearPalfokallPuwuTearbourer.ToString());
}

{% endraw %}

创建 1000 个项目,每个项目有 5 个类,在启动项目引用这 1000 个项目,在启动之后创建 1000 个类,这 1000 个类每个类都在不同的项目里

{% raw %}

        private static void KijeSabacher()
{
var jisqeCorenerairTurpalhee = new DirectoryInfo("StuLartearou"); jisqeCorenerairTurpalhee.Create(); var jairtallworBeakoo = new WhairchooHerdo(); List<string> geeberecereHouroudo = new List<string>(); List<string> xawsosapawTabejetai = new List<string>(); for (int qeltasmisVigallSearniste = 0; qeltasmisVigallSearniste < 1000; qeltasmisVigallSearniste++)
{
string louwebirPemtrasrereYorta = ""; var fismeerurniDawwall = jairtallworBeakoo.LemgeDowbovou(); var nemirchouDamounu = jisqeCorenerairTurpalhee.CreateSubdirectory(fismeerurniDawwall); var beltuzoKoma = @"<Project Sdk=""Microsoft.NET.Sdk""> <PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> </Project>
";
xawsosapawTabejetai.Add(fismeerurniDawwall); File.WriteAllText(Path.Combine(nemirchouDamounu.FullName, fismeerurniDawwall + ".csproj"), beltuzoKoma); for (int roupairDufallne = 0; roupairDufallne < 5; roupairDufallne++)
{
var whowjallKelpirhorWirweSemjaneldroo = jairtallworBeakoo.LemgeDowbovou(); if (roupairDufallne == 0)
{
louwebirPemtrasrereYorta = fismeerurniDawwall + "." + whowjallKelpirhorWirweSemjaneldroo;
} var facoSaijeesereniXaimow = $@"
using System;
using System.Collections.Generic;
using System.Text; namespace {fismeerurniDawwall}
{{
public class {whowjallKelpirhorWirweSemjaneldroo}
{{
public string Foo {{ get; set; }}
}}
}}"; File.WriteAllText(
Path.Combine(nemirchouDamounu.FullName, whowjallKelpirhorWirweSemjaneldroo + ".cs"),
facoSaijeesereniXaimow);
} geeberecereHouroudo.Add(louwebirPemtrasrereYorta);
} var jawjearPalfokallPuwuTearbourer = new StringBuilder(); var dirceDadaipaHowbistairneeQabijel = "CouwharjeMerball";
var suleLougirwhe = jisqeCorenerairTurpalhee.CreateSubdirectory(dirceDadaipaHowbistairneeQabijel); jawjearPalfokallPuwuTearbourer.Append(@"<Project Sdk=""Microsoft.NET.Sdk""> <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup> <ItemGroup>
"); foreach (var ciraZeajanipou in xawsosapawTabejetai)
{
jawjearPalfokallPuwuTearbourer.Append(
$@" <ProjectReference Include=""..\{ciraZeajanipou}\{ciraZeajanipou}.csproj"" />");
jawjearPalfokallPuwuTearbourer.Append("\r\n");
} jawjearPalfokallPuwuTearbourer.Append(@" </ItemGroup> </Project>"); File.WriteAllText(Path.Combine(suleLougirwhe.FullName, dirceDadaipaHowbistairneeQabijel + ".csproj"),
jawjearPalfokallPuwuTearbourer.ToString()); jawjearPalfokallPuwuTearbourer.Clear(); var cepepiSowneKorrer = @"using System;
using System.Diagnostics; namespace CouwharjeMerball
{
class Program
{
static void Main(string[] args)
{
var dafuWhayroubaXouma = new Stopwatch();
dafuWhayroubaXouma.Start();
var kawgeDeesearsofas = new KawgeDeesearsofas();
kawgeDeesearsofas.LurtrajaboPearbubirXinene();
dafuWhayroubaXouma.Stop();
Console.WriteLine(dafuWhayroubaXouma.ElapsedMilliseconds);
}
}
}
";
File.WriteAllText(Path.Combine(suleLougirwhe.FullName, "Program.cs"), cepepiSowneKorrer); jawjearPalfokallPuwuTearbourer.Append(@"namespace CouwharjeMerball
{
class KawgeDeesearsofas
{
public void LurtrajaboPearbubirXinene()
{
"); foreach (var ferosarTadir in geeberecereHouroudo)
{
jawjearPalfokallPuwuTearbourer.Append(" new " + ferosarTadir + "();");
jawjearPalfokallPuwuTearbourer.Append("\r\n");
} jawjearPalfokallPuwuTearbourer.Append(@" }
}
}"); File.WriteAllText(Path.Combine(suleLougirwhe.FullName, "KawgeDeesearsofas.cs"),
jawjearPalfokallPuwuTearbourer.ToString());
}

{% endraw %}

{% raw %}
{% endraw %}

参见

C# 程序内的类数量对程序启动的影响

C# 直接创建多个类和使用反射创建类的性能

C# 性能分析 反射 VS 配置文件 VS 预编译

预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv

dotnet-campus/SourceYard: Add a NuGet package only for dll reference? By using dotnetCampus.SourceYard, you can pack a NuGet package with source code. By installing the new source code package, all source codes behaviors just like it is in your project.

2019-8-31-C#-程序集数量对软件启动性能的影响的更多相关文章

  1. C# 程序集数量对软件启动性能的影响

    本文通过很多的数据测试分析在一个项目引用很多个外部项目和将外部项目的类合并到一个项目之间的启动性能的不同. 通过分析知道了如果一个项目引用了很多项目,而且在启动过程会全部调用这些项目,这时的软件性能会 ...

  2. OSCHINA 公布 2019 年度最受欢迎中国开源软件

    https://www.oschina.net/project 此文章从此处转载:https://www.oschina.net/project/top_cn_2019?utm_source=star ...

  3. agentzh 的 Nginx 教程(版本 2019.07.31)

    agentzh 的 Nginx 教程(版本 2019.07.31) agentzh 的 Nginx 教程(版本 2019.07.31) https://openresty.org/download/a ...

  4. 2019 第十届蓝桥杯大赛软件类省赛 Java A组 题解

    2019 第十届蓝桥杯大赛软件类省赛 Java A组 试题A 题解 ​ 题目最后一句贴心的提示选手应该使用 long (C/C++ 应该使用 long long). ​ 本题思路很直白,两重循环.外层 ...

  5. C# 程序内的类数量对程序启动的影响

    原文:C# 程序内的类数量对程序启动的影响 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.i ...

  6. 2018-10-31-C#-程序内的类数量对程序启动的影响

    title author date CreateTime categories C# 程序内的类数量对程序启动的影响 lindexi 2018-10-31 14:7:6 +0800 2018-10-1 ...

  7. OSGi 对软件复杂度的影响

    出自 深度理解 osgi equinox 原理 1.2.1 OSGi 能让软件开发变得更容易吗 不可否认,OSGi 的入门门槛在 Java 众多技术中算是比较高的,相对陡峭的学习曲线会 为第一次使用 ...

  8. bootchart--检测linux启动性能的软件

    bootchart--检测linux启动性能的软件 摘自http://www-128.ibm.com/developerworks/library/l-boot-faster/index.html?c ...

  9. Win10如何禁止软件运行?win10禁止软件启动的设置方法!禁止人生日历热点快讯的方法

    相信不少使用Win10系统的用户遇到过下载了一款软件进行安装后后续会有接连不断的程序安装到电脑中.他可能似乎一个大家常用的程序,在我们安装好运行的时候会通过后台偷偷下载其他应用安装到我们电脑中,导致系 ...

随机推荐

  1. <每日一题>题目1:简单的注册和登录1.0

    #版本1.0,最基本的注册登录'''1.注册,将账号和密码分别写在不同的文档里面2.登录,分别从账户文档和密码文档进行读取并登录''' #注册 Identity = input("请输入您想 ...

  2. 8.关于ActiveMQ、RocketMQ、RabbitMQ、Kafka一些总结和区别

    这是一篇分享文 转自:http://www.cnblogs.com/williamjie/p/9481780.html  尊重原作,谢谢 消息队列 为什么写这篇文章? 博主有两位朋友分别是小A和小B: ...

  3. C#の单例模式

    版本一: /// <summary>/// A simple singleton class implements./// </summary>public sealed cl ...

  4. new linux setup, yum command

    7  yum list 9  cd /etc/yum.repos.d/ 55  history | grep yum 56  yum -y list screen* 57  yum -y instal ...

  5. Python全栈开发:configparser模块

    #!/usr/bin/env python # -*- coding;utf-8 -*- import configparser # 创建对象 conn = configparser.ConfigPa ...

  6. Android 开发 Camera1_如何使用对焦功能

    前言 Camera1的自动对焦还是有一些坑值得开一个篇幅来讲解,一般对焦Mode有以下几种: Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO 连续自动对焦视 ...

  7. 3.pycharm spark配置

        pycharm 内的环境变量配置     选择相应的spark程序文件的对应的配置信息       PYSPARK_PYTHON:python的安装路径   PYTHONPATH:spark安 ...

  8. [JZOJ5233] 【GDOI模拟8.5】概率博弈

    题目 题目大意 给你一棵树,这棵树上的所有叶子节点的权值是随机的排列. 两个人博弈,从根开始,轮流往下走. 先手希望权值最大,后手希望权值最小. 问期望的最终结果. 思考历程 这场比赛实在是太丧心病狂 ...

  9. RabbitMQ 五种工作模式

    官网介绍:https://www.rabbitmq.com/getstarted.html 五种工作模式的主要特点 简单模式:一个生产者,一个消费者 work模式:一个生产者,多个消费者,每个消费者获 ...

  10. 0818NOIP模拟测试赛后总结

    又挂了…… 120 rank19. 第一次两个机房考不同的题目.一开始并不知道应该做哪套题目. 不明真相的吃瓜群众决定先点开B套.通读三道题,只是觉得T2好水.似乎是红题难度吧……(后来证明是我读错题 ...