为什么 .NET 应用程序至少有一秒的启动延迟?[关闭]

Why do .NET applications have at least a one-second startup delay? [closed]

提问人:amymor 提问时间:10/29/2023 最后编辑:amymor 更新时间:10/30/2023 访问量:144

问:


想改进这个问题吗?更新问题,以便可以通过编辑这篇文章用事实和引文来回答。

23天前关闭。

我一直在寻找一种具有以下参数的语言:

  1. 简单易读的语法。

  2. 能够轻松创建 Windows 用户界面。

  3. 对 Windows 应用程序的本机支持。

  4. 卓越的性能和快速的启动时间。

  5. 可移植性,无需像 10-20 GB Visual Studio IDE 那样进行大量安装。

  6. 它应该已经被广泛使用并拥有一个庞大的社区。

我发现 VB6 满足了我的需求,但不幸的是,它不再受支持。因此,我尝试了 VB .NET。我发现转换非常容易,与 C#/C++ 相比,VB 代码更具可读性和简洁性。正如我所提到的,我不想安装任何东西,所以我没有尝试 .NET 6 和 7。我的目标是尽可能多地使用内置工具或便携式工具。但是,.NET Framework 的问题在于,无论代码的权重或使用的语言(VB 或 C#)如何,启动时间始终保持在 1-2 秒之间。相比之下,VB6 应用程序会立即启动。下面是用 VB .NET 编写的示例:vbc.exe

Imports System.Windows.Forms
Imports System.Drawing

Public Class Form1
    Inherits Form

    Private WithEvents button As New Button()
    Private WithEvents textBox As New TextBox()

    Public Sub New()
        button.Text = "Browse"
        button.Location = New Point(10, 10)
        Me.Controls.Add(button)

        textBox.Location = New Point(10, 40)
        Me.Controls.Add(textBox)
    End Sub
End Class

Module Module1
    Sub Main()
        Application.Run(New Form1)
    End Sub
End Module

我做了什么:

1.

CD C:\Windows\Microsoft.NET\Framework64\v4.0.30319 
NGEN update
  1. 我尝试了(和)编译器的各种选项,例如和。vbc.execsc.exe/optimize[+|-]/platform

  2. 不同版本的 .NET Framework(32 位和 64 位),包括版本 2、3.5 和 4.x.x。

  3. 使用以下命令编译我的应用程序:msbuild.exe

msbuild /property:Configuration=Release;UseDotNetNativeToolchain=true MyFile.vbproj,

以下是 MyFile.vbproj 的内容:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Sdk="Microsoft.NET.Sdk" >
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="DiCalc.vb" />
  </ItemGroup>

<Target Name="Build">
  <Vbc Sources="@(Compile)" OutputAssembly="DiCalc.exe" TargetType="WinExe"/>
</Target>


</Project>

提前致谢。

更新1:

  1. 我的系统上没有安装任何防病毒软件。SmartScreen 筛选器和 Windows Defender 当前均处于禁用状态。
  2. 我不使用任何共享网络文件夹。实际上,我在 M.2 NVMe SSD 上对其进行了测试。

更新2:以下是更详细的测试:

VB6 和 VB.NET-x86 视频

VB中。NET-x64 视频

测试.VB

Imports System.Windows.Forms
Imports System.Drawing

Public Class Form1
    Inherits Form
    Private button As New Button()


    Public Sub New()
        Me.BackColor = Color.FromArgb(14, 14, 14)
        Me.ForeColor = Color.FromArgb(240, 240, 240)
        
        button.Text = "Browse"
        button.Location = New Point(10, 10)
        button.BackColor = Color.FromArgb(14, 14, 14)
        button.ForeColor = Color.FromArgb(240, 240, 240)
        Me.Controls.Add(button)

    End Sub
End Class

Module Module1
    Sub Main()
        Application.Run(New Form1)
    End Sub
End Module

编译命令:

64 倍

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\vbc.exe /t:winexe /platform:x64 /out:VB.NET-x64.exe test.vb

x86的

C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe /t:winexe /platform:x86 /out:VB.NET-x86.exe test.vb

平均延迟:

VB.NET-x64.exe => ~320 ms
VB.NET-x86.exe => ~650 ms
VB6-x86.exe    => ~80 ms

因此,VB6 的启动时间比 VB.NET 快 4 到 8 倍。

注意:要查看实际延迟,请确保禁用动画,并通过文件夹选项a启用资源管理器中的单击。

更新 3:我下载了 .NET 8 SDK zip 存档来测试它并确定提前 (AOT) 编译是否会缩短启动时间,类似于 VB6。以下是 .vbproj 文件的内容:

<Project Sdk="Microsoft.NET.Sdk" >
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <PublishAot>true</PublishAot>
    <StripSymbols>true</StripSymbols>
    <PublishTrimmed>false</PublishTrimmed>
    <SelfContained>true</SelfContained>
    <PublishReadyToRun>true</PublishReadyToRun>
  </PropertyGroup>
<ItemGroup>
    <PackageReference Include="System.Windows.Forms" />
</ItemGroup>
</Project>

编译命令:

dotnet.exe build /p:Configuration=Release /p:UseNativeAOT=true

结果是一个大小约为 150MB 的应用程序,但延迟与以前相同。

.NET Windows vb.net VB6 VBC

评论

3赞 Olivier Jacot-Descombes 10/29/2023
VB 的很多功能都来自功能强大的 IDE Visual Studio,您无需在部署计算机上安装它。将于 2023 年 11 月中旬推出的 .NET 8 在缩短启动时间方面做了很多工作。它还提供了提前编译 (AOT) 选项,从而进一步缩短了启动时间。
0赞 amymor 10/30/2023
感谢您的回复。我目前不是在寻找一个强大的解决方案;供个人使用。我很高兴听到 .NET 8 即将发布的版本,但我知道需要在目标计算机上安装它才能运行应用程序,这是我想避免的步骤。我们当然可以在应用程序中包含依赖项,从而消除安装的需要。但是,应用程序大小会显着增加,我宁愿不这样做。例如,在 .NET Framework v4 中,上述窗体的大小仅为 8KB。但是,我相信 .NET 6 和 7 中的大小将在 50-100MB 之间。
1赞 Olivier Jacot-Descombes 10/30/2023
是的。Visual Studio 和 .NET Framework 是两个不同的东西。您需要 Framework 来运行应用程序。中的 AOT。与以前的实现相比,NET8 创建的 .exe 文件更小。
0赞 Albert D. Kallal 10/30/2023
加载该程序时不应有任何明显的延迟 - 请参阅下面的帖子。
0赞 MarkL 10/31/2023
也许一些时间旅行调试可以让你深入了解你的代码启动时发生了什么?

答:

1赞 Albert D. Kallal 10/30/2023 #1

首先,我的 vb.net 应用程序都没有在启动时出现这样的延迟。

如果创建 vb.net Windows .net Framework 窗体应用程序,则启动时间不会显示延迟,甚至没有可察觉的启动延迟。

所以,让我们做一个hello world:

File->new 项目。

这个:

enter image description here

因此,让我们构建该类 hello world 示例。

我们在窗体上拖动一个按钮,从而编写以下代码:

enter image description here

然后 f5 运行..

(实际上,我们使用鼠标并点击开始按钮)。

我们看到了这一点,并且看到很少的延迟:enter image description here

当然,我们从Visual Studio运行它,但是让我们右键单击项目,选择“在浏览中打开文件夹”,然后从Windows资源管理器运行.exe文件(而不是从Visual Studio运行/启动)。因此,让我们从 Windows 资源管理器(甚至命令提示符)启动 .exe 文件。

所以,我们现在有了这个文件夹,当我单击 .exe 文件时,我没有看到 2 秒的等待,我没有看到 1 秒的等待,事实上,表单启动时根本没有任何感知延迟。

所以,我看到这个:

enter image description here

现在,我正在使用屏幕转 gif,它以每秒 15 帧的速度运行,所以你看到的是比在你自己的计算机上这样做“有点”慢的效果和响应时间。

但是,screentogif(我使用的屏幕捕获软件)在我单击鼠标时确实显示一个圆圈。因此,当我双击.exe文件(运行它)时,可以看到鼠标单击“圆圈”从screentogif软件闪烁两次。

现在,我没有计算捕获的视频帧数,但它看起来不超过 1 帧延迟。所以,这至少是 1/15 秒,但实际上很可能更短的时间。

换句话说,我们加载和运行该 .exe 文件的时间不到 1/10 秒......

即使我使用 .net core 创建上述相同的项目,我在这里也看不到也找不到任何可察觉的启动延迟。

所以,我不知道.net有一些很大的延迟或启动时间,而且在启动时间方面,它真的不需要运行任何太大的不同,然后与VB6 .exe的启动时间相比。

我想在非常弱的旧硬件上,VB6 可能会有更好的启动时间,但它不应该非常明显,而且它肯定不在 1-2 秒范围内。对于一个非常大的 .net 应用程序,在首次运行时,您经常会看到延迟,因为该.exe实际上尚未编译为机器代码!!当您构建 .net .exe 时,该 exec 实际上还没有编译的机器代码)。它有所谓的 p 代码(就像 VB5/6 一样)。这个所谓的“IL”代码(中间语言或所谓的“p代码”)尚未编译,并且这种代码编译仅在您第一次运行代码时发生!!因此,.net 有一个 JIT(实时编译器系统),代码会在你使用它时和首次运行时进行编译。但是,正如我所指出的,对于上述简单和小型应用程序,在启动时根本不应该察觉到这种延迟。

而编译只需要发生一次,之后,编译后的代码就会被记住。这与磁盘缓存和程序加载无关 - 它仅特定于用于编译和运行 .exe 文件的 JIT 系统。

这表明这里还有其他一些问题,例如您的病毒软件扫描并阻止 .exe 启动,直到病毒扫描软件可以首先完成对 .exe 文件的检查。

或者,您在此处使用了一些网络共享文件夹,或者您没有与我们共享的其他一些重要细节。

事实上,如上所示,从 Visual Studio 2022 中按 f5 甚至不需要 2 秒!但是按 f5 是完全编译,+ 构建,然后运行。(多个操作,其中一个是用户永远不会看到的)。

因此,通过双击该文件或从命令提示符键入 .exe 文件名来运行从该 VS 项目创建的结果 .exe 文件肯定会启动,并在一秒内运行,更不用说两秒了。

请记住,我是在笔记本电脑上运行的,而不是高端规格的笔记本电脑,更不用说更好、更强大的台式电脑了。

而且,如果我创建一个 .net 核心 winforms .exe,那么再一次,我不会察觉到任何延迟。由于构建,我当然在 .bin 文件夹中看到更多文件,但在使用 .net core 时我没有看到任何变化或加载时间增加。我也许可以尝试冷启动(重新启动),但我怀疑它会有什么不同。

评论

0赞 MarkL 10/30/2023
此答案的感知负载速度与 OP 之间的另一个可能差异是驱动器类型。也许 Albert 有一个 SSD,而 OP 有一个旋转盘片驱动器?
0赞 amymor 10/30/2023
谢谢。但是,让我们简单地创建一个 VB 文件并使用 vbc 对其进行编译。().x86 的延迟更明显,x64 更好一些,但仍然无法击败 VB6。此外,对窗体和按钮使用黑色配色方案,因为 Windows 在加载窗体和按钮之前会显示一个空白的白色区域,因此您也会注意到窗体加载的延迟,即使它小于启动延迟。此外,禁用动画并在资源管理器中启用单击并捕获至少 60fps。我也更新了我的帖子,也读到了这一点。C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe /t:winexe /platform:x86 test.vb
0赞 amymor 10/30/2023
@MarkL我更新了我的帖子。我有一个 M.2 NVMe SSD。