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 个类,在启动之后调用这 5000 个类里的 1000 个
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());
}
创建 1000 个项目,每个项目有 5 个类,在启动项目引用这 1000 个项目,在启动之后创建 1000 个类,这 1000 个类每个类都在不同的项目里
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());
}
参见
预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv
我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新
如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# 程序集数量对软件启动性能的影响的更多相关文章
- 2019-8-31-C#-程序集数量对软件启动性能的影响
title author date CreateTime categories C# 程序集数量对软件启动性能的影响 lindexi 2019-08-31 16:55:58 +0800 2018-10 ...
- dotnet 使用 Crossgen2 对 DLL 进行 ReadyToRun 提升启动性能
我对几个应用进行严格的启动性能评估,对比了在 .NET Framework 和 dotnet 6 下的应用启动性能,非常符合预期的可以看到,在用户的设备上,经过了 NGen 之后的 .NET Fram ...
- bootchart--检测linux启动性能的软件
bootchart--检测linux启动性能的软件 摘自http://www-128.ibm.com/developerworks/library/l-boot-faster/index.html?c ...
- Windows 程序启动性能优化(先载入EXE,后载入DLL,只取有限的代码载入内存,将CPU的IP指向程序的入口点)
一.重定位链接时重定位:目标文件一般由多个节组成,编译器在编译每个目标文件时一般都是从0地址开始生成代码.当多个代码节合成一个代码段时,需要根据其在最终代码段中的位置做出调整.同时,链接器需要对已经解 ...
- C# 程序内的类数量对程序启动的影响
原文:C# 程序内的类数量对程序启动的影响 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.i ...
- 2019-8-31-dotnet-启动-JIT-多核心编译提升启动性能
title author date CreateTime categories dotnet 启动 JIT 多核心编译提升启动性能 lindexi 2019-08-31 16:55:58 +0800 ...
- 2018-10-31-C#-程序内的类数量对程序启动的影响
title author date CreateTime categories C# 程序内的类数量对程序启动的影响 lindexi 2018-10-31 14:7:6 +0800 2018-10-1 ...
- dotnet 启动 JIT 多核心编译提升启动性能
用2分钟提升十分之一的启动性能,通过在桌面程序启动 JIT 多核心编译提升启动性能 在 dotnet 可以通过让 JIT 进行多核心编译提升软件的启动性能,在默认托管的 ASP.NET 程序是开启的, ...
- iOS App 启动性能优化
1. App启动过程 解析Info.plist 加载相关信息,例如如闪屏 沙箱建立.权限检查 Mach-O加载 如果是胖二进制文件,寻找合适当前CPU类别的部分 加载所有依赖的Mach-O文件(递归调 ...
随机推荐
- Directx11教程(33) 纹理映射(3)
原文:Directx11教程(33) 纹理映射(3) 现在我们在myTutorialD3D11_5的基础上,来逐步编码实现纹理映射,之所以在myTutorialD3D11_5基础上改写,是 ...
- 2019-11-12-WPF-添加窗口消息钩子方法
title author date CreateTime categories WPF 添加窗口消息钩子方法 lindexi 2019-11-12 18:46:53 +0800 2019-06-05 ...
- Python 局部变量转为全局变量
- 【风马一族_php】NO4_php基础知识
原文来自:http://www.cnblogs.com/sows/p/6017018.html(博客园的)风马一族 侵犯版本,后果自负 回顾 运算符:算术运算符.逻辑运算符.比较运算符.位运算符.赋值 ...
- Ubuntu官方源
由于国内使用官方源导致下载速度慢等各方面原因,很多人将官方源替换成阿里源等,但是某些应用安装会报错.现将官方源分享如下: 备份当前源: 执行命令:# sudo cp /etc/apt/sources. ...
- mariadb配置文件优化参数
mariadb数据库优化需要根据自己业务需求以及根据硬件配置来进行参数优化,下面是一些关于mariadb数据库参数优化的配置文件. 1 如下为128G内存32线程处理器的mariadb配置参数优化: ...
- 在Swift中检查API的可用性
http://www.cocoachina.com/swift/20150901/13283.html 本文由CocoaChina译者ALEX吴浩文翻译自Use Your Loaf博客 原文:Chec ...
- Java转iOS-第一个项目总结(2):遇到问题和解决方案
目录1.UITableView滑动卡顿的优化 2.右滑手势返回 3.添加页面统计 4.debug版和release版 5.关于页面刷新 6.关于页面布局 7.推荐博客 遇到问题和解决方案 本文是Jav ...
- 巨蟒python全栈开发-第11阶段 ansible3_2入门八个模块
大纲: 1.file模块 2.fetch模块 3.yum&&pip模块 4.service模块 5.cron模块 6.user模块 7.group模块
- 瑞星推国内唯一Linux系统杀毒软件 国产操作系统还需国产安全软件保护
近来在IT领域最爆炸的新闻莫过于5月20日中央国家机关政府採购中心下发通知.要求中央机关採购所有计算机类产品不同意安装Windows 8.而改用国产Linux操作系统. 此消息一出,立马引起各界关注. ...