首页 > 编程语言 >几行代码提升.NET应用程序启动速度

几行代码提升.NET应用程序启动速度

时间:2024-11-16 23:15:54浏览次数:3  
标签:启动 几行 耗时 JIT 多核 应用程序 Stopwatch NET

几行代码提升.NET应用程序启动速度

为什么使用多核JIT技术

.NET Framework最早发布于2002年,当时电脑的硬件性能并不强大,.NET Framework的设计人员可能考虑绝大部分电脑都是单核处理器,并未对多核处理器进行足够的优化。随着计算机硬件性能的逐渐提高,之前基于单核处理器设计的.NET Framework已经无法满足用户期望应用程序能够快速启动的愿望,因此设计人员引入了多核JIT技术(Multicore JIT),使用多核JIT技术能提升.NET Framework应用程序的启动速度。

多核JIT技术原理

要看到多核JIT提速的效果,我们需要运行应用程序两次,第一次运行应用程序时(记录模式),JIT编译器将所有需要编译的函数均记录下来,等到CLR启动完毕,将记录的这些方法通过配置文件保存至磁盘。

当第二次运行程序时,程序会预先从磁盘加载配置文件,获取到需要编译的函数,然后在后台线程进行JIT编译,如果是多核处理器,就会在另外的核心上并行编译,因此可能在主线程运行之前即可完成即时编译,从而提升应用程序的启动速度,减少白屏时间。

如何使用多核JIT技术

多核JIT技术可以提升所有基于.net framework 4.5以上应用程序的启动速度,包括但不限于WPF桌面应用程序、WinForm桌面应用程序以及ASP .NET。

WPF桌面应用程序

WPF应用程序只需要在App.xaml.cs中的构造函数添加以下内容:

public App()
{
    CreateProfileOptimization();
}

private static void CreateProfileOptimization()
{
    try
    {
        string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MyApp");
        Directory.CreateDirectory(path);
        // 设置JIT profile文件存储的目录
        ProfileOptimization.SetProfileRoot(path);
        // 通过加载指定的profile文件来使能多核JIT
        ProfileOptimization.StartProfile("startup.profile");
    }
    catch (UnauthorizedAccessException)
    {
    }
    catch (IOException)
    {
    }
}

其中MyApp可以替换成你的应用的名称,生成的加速文件存储在C:\Users\用户名\AppData\Local\MyApp目录下。

WinForm桌面应用程序

WinForm应用程序在Program.cs文件中添加以下内容启动多核JIT:

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
    CreateProfileOptimization();

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

private static void CreateProfileOptimization()
{
    try
    {
        string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MyApp");
        Directory.CreateDirectory(path);
        // 设置JIT profile文件存储的目录
        ProfileOptimization.SetProfileRoot(path);
        // 通过加载指定的profile文件来使能多核JIT
        ProfileOptimization.StartProfile("startup.profile");
    }
    catch (UnauthorizedAccessException)
    {
    }
    catch (IOException)
    {
    }
}

多核JIT使用的实际效果

测试条件:

测试参数描述
CPU13th Gen Intel® Core™ i5-13600KF 3.50 GHz 14核心20线程
内存32GB DDR5 4800MHz
硬盘KINGSTON SNV2S500G固态硬盘
操作系统Windows 11专业版 23H2
.NET6.0

测试程序我们使用开源的OxyPlot图表控件进行测试,测试的OxyPlot版本为2.1.2,通过对WpfExamples进行改造,来评估程序的启动时间,首先需要将项目设置为控制台启动,通过控制台来打印程序的启动时间:
设置为控制台程序

未使用多核JIT启动耗时

我们需要对源码进行一下改造来计算启动耗时,通过Stopwatch来精确计算程序的启动时间,首先在App.xaml.cs中添加以下代码:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    public static Stopwatch Stopwatch { get; private set; }

    public App()
    {
        Stopwatch = new Stopwatch();
        Stopwatch.Start();
    }
}

在App类的构造函数中初始化Stopwatch并开始计时,然后在主窗体MainWindow.cs的Loaded事件处理函数中停止Stopwatch,并将最终耗时打印在控制台上:

/// <summary>
/// Initializes a new instance of the <see cref="MainWindow" /> class.
/// </summary>
public MainWindow()
{
    this.Loaded += this.MainWindow_Loaded;
    InitializeComponent();
    this.DataContext = this;
    this.Examples = this.GetExamples(this.GetType().Assembly).OrderBy(e => e.Title).ToArray();
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    App.Stopwatch.Stop();
    Console.WriteLine($"启动耗时{App.Stopwatch.ElapsedMilliseconds}毫秒");
}

在MainWindow的构造函数中,我们订阅了Loaded事件,并在MainWindow_Loaded事件中停止了Stopwatch,从而计算出了应用程序启动的时间,通过10次测试,计算启动的平均耗时,每次耗时及平均耗时见下表所示:

序号耗时(mS)
1400
2401
3401
4385
5390
6393
7406
8399
9403
10398
平均397.6

未使用多核JIT启动耗时截图:
未使能JIT启动耗时

使用多核JIT启动耗时

基于原有代码,将App.xaml.cs进行改造,添加多核JIT的支持:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    public static Stopwatch Stopwatch { get; private set; }

    public App()
    {
        Stopwatch = new Stopwatch();
        Stopwatch.Start();

        CreateProfileOptimization();
    }

    private static void CreateProfileOptimization()
    {
        try
        {
            string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "WpfExamples");
            Directory.CreateDirectory(path);
            // 设置JIT profile文件存储的目录
            ProfileOptimization.SetProfileRoot(path);
            // 通过加载指定的profile文件来使能多核JIT
            ProfileOptimization.StartProfile("startup.profile");
        }
        catch (UnauthorizedAccessException)
        {
        }
        catch (IOException)
        {
        }
    }
}

改造完毕后,编译,运行,注意!!!第一次运行速度不会有提升,第二次运行时速度才会提升,同样运行10次,每次运行耗时及平均耗时如下表所示:

序号耗时(mS)
1344
2348
3344
4346
5342
6348
7347
8344
9351
10349
平均346.3

使用多核JIT启动耗时截图:
使用多核JIT启动耗时

性能对比

未使用多核JIT应用启动平均时间为397.6毫秒,使用多核JIT应用平均启动时间为346.3,启动速度提升了12.9%。由于本次测试使用的电脑配置相对较高,因此差距并不是很大,对于单核性能较弱的电脑,实际测试启动速度提升率会更高,平均提速大约为10%~50%,大家可以自行验证一下。

标签:启动,几行,耗时,JIT,多核,应用程序,Stopwatch,NET
From: https://blog.csdn.net/2402_88871930/article/details/143697255

相关文章

  • esxi6.7 安装仿真网络模拟器PNetLab v6版本
    安装仿真网络模拟器PNetLabv6版本Installationinstructions-PNetLabv6BETAreleaseReadthefullinstructionsandimportantnotesbeforestartingtheprocess.Afteryoufinishreadingthem,followtheprocessstepbystep.Step1DownloadtheUbuntuServer......
  • 什么是Google Kubernetes Engine (GKE) 中Node Pool 和 Pod
    在GoogleKubernetesEngine(GKE)中,NodePool和Pod是Kubernetes集群中的两个关键概念,它们的关系密切但作用不同:简单类比:想象一个工厂(Kubernetes集群):NodePool: 是工厂里的多个相同的车间,每个车间都有相同的机器设备。Pod: 是车间里的生产线,每个生产线都在进行不......
  • Profinet转EtherNet/IP协议网关功能及配置
    在现代工业自动化领域,Profinet转EtherNet/IP的互联互通至关重要,远创智控YC-PN-EIP设备是优秀的解决方案。它拥有高效协议转换能力,带来便捷体验,提升企业生产效率与智能化水平。主要功能包括精准的数据转换和传输。突出特点与优势有性能稳定可靠、操作简易。技术参数涵盖传输速率......
  • Profinet转CC-Link IEFB主站协议网关功能及配置
    在现代工业自动化领域,Profinet转CC-LinkIEFB的互联互通至关重要,远创智控YC-CCLKIEM-PN设备是优秀的解决方案。它拥有高效协议转换能力,带来便捷体验,提升企业生产效率与智能化水平。主要功能包括精准的数据转换和传输。突出特点与优势有性能稳定可靠、操作简易。技术参数涵盖传......
  • Profinet转CC-Link IE协议网关功能及配置
    在现代工业自动化领域,Profinet转CC-LinkIE的互联互通至关重要,远创智控YC-PN-CCLKIE设备是优秀的解决方案。它拥有高效协议转换能力,带来便捷体验,提升企业生产效率与智能化水平。主要功能包括精准的数据转换和传输。突出特点与优势有性能稳定可靠、操作简易。技术参数涵盖传输速......
  • 微服务组件【负载均衡】Netflix Ribbon
    微服务组件【负载均衡】NetflixRibbonNetflixRibbon**RestTemplate:负载均衡拦截**HttpAccessor#createRequestInterceptingRequestExecution#executeRibbon负载均衡LoadBalancerClientILoadBalancerIRuleServer博主默语带您GotoNewWorld.✍个人主页......
  • Pointnet++改进68:添加FFCM |融合傅里叶卷积
    简介:1.该教程提供大量的首发改进的方式,降低上手难度,多种结构改进,助力寻找创新点!2.本篇文章对Pointnet++特征提取模块进行改进,加入,提升性能。3.专栏持续更新,紧随最新的研究内容。目录1.理论介绍2.修改步骤2.1步骤一     2.2步骤二     2.3步骤三1......
  • 在 PowerShell 中,New-NetLbfoTeam 和 New-NetSwitchTeam 都用于创建网络适配器团队(Net
    在PowerShell中,New-NetLbfoTeam和New-NetSwitchTeam都用于创建网络适配器团队(NetworkAdapterTeaming),但它们针对的是不同的网络架构和技术。下面是这两个cmdlet的详细分析与区别,并以表格形式呈现。1. New-NetLbfoTeamNew-NetLbfoTeam是用于在本地计算机上配置网络......
  • 【K8s】专题十五(2):Kubernetes 网络之 CNI
    本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口| 精选文章 | Kubernetes |Docker|Linux |羊毛资源 | 工具推荐 |往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决......
  • VBA:聚光灯所有的技术都在这里了(纯干货,含vb.net)
     聚光灯效果         大多数人想要自己做聚光灯首先想到的是条件格式,条件格式有很多弊端,第一点对Excel的撤回功能有影响,第二点只对单个工作簿有作用,每次新的工作簿就没用了.第三点影响工作簿原有的格式.今天介绍两种完美聚光灯的方案VBA完美聚光灯原理:条件格......