分析:
实时编译,也就是JIT,具有跨平台的优点,实时编译也保证了在新的硬件技术推出后,原先写的代码可以不需要重新编译就直接享用新的技术带来的优点。 但JIT本身作为一种技术,当然存在执行效率低、第一次启动时间长的缺点。
目前有两种方式可以产生本机的机器代码:实时编译(JIT)和预编译方式(产生Native Image)。
JIT的全称是实时编译(Just-In-Time),程序员掌握JIT工作原理是很有必要的。当需要校调对性能要求很高的代码时,MSIL通常不是最好的做法,JIT优化器会默认地优化程序代码。
使用过ildasm或Reflector工具的程序员会发现在Release和Debug模式下产生的MSIL代码几乎完全相同,但由于使用JIT优化,因此Release模式的代码运行效率会如此迅速。
笔者将通过Native Code(本地代码)来查找系统所做的优化,只有当要调用某个方法时,JIT编译器才会将MSIL的方法体编译为相应的本机机器码,这样做可以优化程序的工作集。首先看一段简单的测试代码:
namespace MyConsole
{
class HelloKitty //定义一个简单类HelloKitty
{
static void Main(string[] args) //主程序
{
Console.WriteLine("这是一个MSIL测试程序,Hello Kitty"); //输出一个测试信息
Console.Read();
}
}
}
下面看一下Debug模式下测试代码的本地代码,如下所示。
//将上面C#代码编译成MSIL代码
namespace MyConsole
{
class HelloKitty //定义一个简单类HelloKitty
{
static void Main(string[] args) //主程序
{
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,30h
00000009 xor eax,eax
0000000b mov dword ptr [ebp-10h],eax
0000000e xor eax,eax
00000010 mov dword ptr [ebp-1Ch],eax
00000013 mov dword ptr [ebp-3Ch],ecx
00000016 cmp dword ptr ds:[009892FCh],0
0000001d je 00000024
0000001f call 764F8F29
00000024 nop
Console.WriteLine("这是一个MSIL测试程序,Hello Kitty"); //输出一个测试信息
00000025 mov ecx,dword ptr ds:[022C2088h]
0000002b call 75BC2280
00000030 nop
Console.Read();
00000031 call 75BC2D14
00000036 nop
}
00000037 nop
00000038 lea esp,[ebp-0Ch]
0000003b pop ebx
0000003c pop esi
0000003d pop edi
0000003e pop ebp
0000003f ret
以下是Release模式下的代码:
namespace MyConsole
{
class HelloKitty //定义一个简单类HelloKitty
{
static void Main(string[] args) //主程序
{
Console.WriteLine("这是一个MSIL测试程序,Hello Kitty"); //输出一个测试信息
00000000 push ebp
00000001 mov ebp,esp
00000003 push eax
00000004 mov dword ptr [ebp-4],ecx
00000007 cmp dword ptr ds:[009992FCh],0
0000000e je 00000015
00000010 call 764E8F29
00000015 mov ecx,dword ptr ds:[022D2088h]
0000001b call 75BB2280
Console.Read();
00000020 call 75BB2D14
00000025 nop
}
00000026 nop
00000027 mov esp,ebp
00000029 pop ebp
0000002a ret
注意:同一段测试代码生成的Release模式下只有25行,而Debug模式下却有37行。Release模式下比Debug模式下小很多,也简洁清晰很多。
在实时编译的过程中,JIT引擎会查找一个包含该类型所有方法存根的数据结构,对于未编译成机器代码的方法,存根会包含一个调用JIT的简单命令,当该方法的实时编译结束后,存根的命令会被替换成一条简单的Jmp指令,使得代码跳转到该方法的机器代码位置。
这样导致整个项目的大小进一步的得到了优化,更能高效的执行本地代码。
总结:
JIT的全称是实时编译(Just-In-Time),描述一种操作的词组,该操作只有在必要时才执行,如实时编译或实时对象激活。
运行时需要代码时,将Microsoft中间语言 (MSIL) 转换为机器码的编译。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?