原文

https://zhuanlan.zhihu.com/p/352463394

增加了少部分自己的理解

什么是跨平台

首先,什么是跨平台?

跨平台:一次编译,不需要任何代码修改,应用程序就可以运行在任意在平台上跑,即代码不依赖于操作系统,也不依赖硬件环境。

游戏肯定需要跨平台,不能只支持一种平台,不然每个对应的平台做出一种对应的编译器,那真的会累死。所以对于跨平台的需求,对于游戏开发而言,很重要。Unity的架构需求设计当然也需要这个特性。

Mono介绍

Mono是一个由Xamarin公司所主持的自由开放源码项目。
Mono的目标是在尽可能多的平台上使.net标准的东西能正常运行的一套工具,核心在于“跨平台地让.net代码能运行起来“。
Mono组成组件:C# 编译器,CLI虚拟机,以及核心类别程序库。
Mono的编译器负责生成符合公共语言规范的映射代码,即公共中间语言(Common Intermediate Language,CIL),我的理解就是工厂方法实现不同解析。

什么是IL

IL的全称是 Intermediate Language,IL是与CPU无关的机器语言,能访问和操作对象类型,并提供了指令来创建和初始化对象、调用对象上的虚方法以及直接操作数组元素。甚至提供了抛出和捕捉异常的指令来实现错误处理。可将IL视为一种面向对象的及其语言。很多时候还会看到CIL(特指在.Net平台下的IL标准)。翻译过来就是中间语言。
它是一种属于通用语言架构和.NET框架的低阶的人类可读的编程语言。
CIL类似一个面向对象的汇编语言,并且它是完全基于堆栈的,它运行在虚拟机上(.Net Framework, Mono VM)的语言。

什么是CLR

CLR,公共语言运行时(公共语言运行库),是一个可由多种编程语言使用的“运行时”。CLR的核心功能(比如内存管理、程序集加载、安全性、异常处理和线程同步)可由面向CLR的所有语言使用。

CLR,IL,JITCompiler

在运行时,CLR根本不关心开发人员用哪一种语言写源代码。可用任何编程语言开发代码,只要编译器是面向CLR的。

CLR实际不和模块工作。它和程序集工作。程序集(assembly)是抽象概念,它是一个或多个模块/资源文件的逻辑性分组。其次,程序集是重用、安全性以及版本控制的最小单元。取决于你选择的编译器或工具,即可生成单文件程序集,也可生成多文件程序集。在CLR的世界中,程序集相当于组件

托管程序集同时包含元数据和IL。开发人员一般用高级语言进行编程。它们的编译器生成IL,IL也能使用汇编语言编写。

高级语言通常只公开了CLR全部功能的一个子集。然而,IL汇编语言允许开发人员访问CLR的全部功能。

为了执行方法,首先必须把方法的IL转换成本机CPU指令,这是CLR的JIT(just int time或者即时)编译器的职责。

Main方法首次调用WriteLine时,JITCompiler函数会被调用。JITCompiler函数负责将方法的IL代码编译成CPU指令。由于IL是即时编译的,所以通常将CLR的这个组件称为JITter或者JIT编译器。

JITCompiler函数被调用时,它知道要调用的是哪个方法,以及具体是什么类型定义了该方法。然后,JITCompiler会在定义(该类型的)程序集的元数据中查找被调用方法的IL。接着,JITCompiler验证IL代码,并将IL代码编译成本机CPU指令。本机CPU指令保存到动态分配的内存块中。然后,JITCompiler回到CLR为类型创建的内部数据结构,找到与被调用方法对应的那条记录,修改最初对JITCompiler的引用,使其指向内存块(其中包含了刚才编译好的本机CPU指令)的地址。最后,JITCompiler函数跳转到内存块中的代码。这些代码正式WriteLine方法的具体实现。代码执行完毕返回时,回到Main中的代码,并像往常一样执行。

现在,在第二次调用WriteLine时,会直接执行内存块中的代码,跳过JIPCompiler函数。

方法仅在首次调用时才会有一些性能损失。以后对该方法的所有调用都以本机代码的形式全速运行,无需重新验证IL并把它编译成本机代码。

JIT编译器将本机CPU指定存储到动态内存中。这意味着一旦应用程序终止,编译好的代码也会被丢弃。所以,再次运行应用程序或者同时启动应用程序的两个实例,JIT编译器必须再次将IL编译成本机指令。

JIT编译的优点

  • 构建应用非常快
  • 由于Mono的JIT(Just In Time compilation ) 机制, 所以支持更多托管类库
  • 支持运行时代码执行
  • 必须将代码发布成托管程序集(.dll 文件 , 由mono或者.net 生成 )
  • Mono VM在各个平台移植异常麻烦,有几个平台就得移植几个VM(WebGL和UWP这两个平台只支持 IL2CPP)
  • Mono版本授权受限,C#很多新特性无法使用
  • iOS仍然支持Mono , 但是不再允许Mono(32位)应用提交到Apple Store

什么是AOT

程序运行之前,将.exe或.dll文件中的CIL的byte code部分转译为目标平台的原生码并且存储,程序运行中仍有部分CIL的byte code需要JIT编译。

什么是Full AOT

程序运行前,将所有源码编译成目标平台的原生码。

编译器

C#编译器mcs:将C#编译为IL。

Mono Runtime编译器:将IL转移为原生码

Unity跨平台的原理

Mono运行时编译器支持将IL代码转为对应平台原生码。

IL可以在任何支持CLI(通用语言环境结构)中运行,IL的运行是依托于Mono运行时。

IOS不支持JIT编译的原因

IOS并非把JIT禁止了。或者换个句式讲,IOS封了内存(或者堆)的可执行权限,相当于变相的封锁了JIT这种编译方式。

机器码被禁止映射到内存,即封存了内存的可执行权限,变相的封锁了jit编译方式。

IL2CPP

IL2CPP分为两个独立的部分:

1. AOT(静态编译)编译器:把IL中间语言转换成CPP文件

2. 运行时库:例如垃圾回收、线程/文件获取(独立于平台,与平台无关)、内部调用直接修改托管数据结构的原生代码的服务与抽象

AOT编译器

IL2CPP AOT编译器名为il2cpp.exe。
在Windows上,您可以在Editor \ Data \ il2cpp目录中找到它。
在OSX上,它位于Unity安装的Contents / Frameworks / il2cpp / build目录中
il2cpp.exe 是由C#编写的受托管的可执行程序,它接受我们在Unity中通过Mono编译器生成的托管程序集,并生成指定平台下的C++代码。

IL2CPP工具链:

运行时库

IL2CPP技术的另一部分是运行时库(libil2cpp),用于支持IL2CPP虚拟机的运行。
这个简单且可移植的运行时库是IL2CPP技术的主要优势之一!
通过查看我们随Unity一起提供的libil2cpp的头文件,您可以找到有关libil2cpp代码组织方式的一些线索
您可以在Windows的Editor \ Data \ PlaybackEngines \ webglsupport \ BuildTools \ Libraries \ libil2cpp \ include目录中找到它们
或OSX上的Contents / Frameworks / il2cpp / libil2cpp目录。

为什么要转成CPP

(1)运行效率快

根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升。

(2)Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成

Mono的跨平台是通过Mono VM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM肯定是不能满足需求的。所以针对不同的新平台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug。这非常耗时耗力。这些能移植的平台还好说,还有比如WebGL这样基于浏览器的平台。要让WebGL支持Mono的VM几乎是不可能的。

(3)可以利用现成的在各个平台的C++编译器对代码执行编译期优化,这样可以进一步减小最终游戏的尺寸并提高游戏运行速度。

(4)由于动态语言的特性,他们多半无需程序员太多关心内存管理,所有的内存分配和回收都由一个叫做GC(Garbage Collector)的组件完成。

虽然通过IL2CPP以后代码变成了静态的C++,但是内存管理这块还是遵循C#的方式,这也是为什么最后还要有一个 IL2CPP VM的原因:它负责提供诸如GC管理,线程创建这类的服务性工作。

但是由于去除了IL加载和动态解析的工作,使得IL2CPP VM可以做的很小并且使得游戏载入时间缩短

Mono和IL2CPP编译区别

使用Mono的时候,脚本的编译运行如下图所示:

3大脚本被编译成IL,在游戏运行的时候,IL和项目里其他第三方兼容的DLL一起,放入Mono VM虚拟机,由虚拟机解析成机器码,并且执行IL2CPP做的改变由下图红色部分标明:

在得到中间语言IL后,使用IL2CPP将他们重新变回C++代码,然后再由各个平台的C++编译器直接编译成能执行的原生汇编代码。

IL2CPP优点

  • 相比Mono, 代码生成有很大的提高
  • 可以调试生成的C++代码
  • 可以启用引擎代码剥离(Engine code stripping)来减少代码的大小
  • 程序的运行效率比Mono高,运行速度快
  • 多平台移植非常方便
  • 相比Mono构建应用慢
  • 只支持AOT(Ahead of Time)编译

IL2CPP比较适合开发和发布项目 ,但是为了提高版本迭代速度,可以在开发期间切换到Mono模式(构建应用快)。

Mono和IL2CPP相关推荐

  1. unity3d中ScriptingBackend选择mono和il2cpp的区别

    unity3d中ScriptingBackend选择mono和il2cpp的区别 在iOS和Android上,在Player Settings中选择mono或il2cpp脚本后端.要更改脚本后端,请转 ...

  2. Unity 中的 .NET、Mono 和 IL2CPP

    接 上一篇 继续了解,重点是 IL2CPP. 一.Unity 的脚本后端 Unity 使用开源 .NET 平台,以确保使用 Unity 创建的应用程序可以跨平台运行. 脚本后端(scripting b ...

  3. Unity Mono和IL2CPP的区别

    *目录 Unity是如何实现跨平台的? Mono介绍 IL2CPP介绍 Mono与IL2CPP的区别* 一.Unity是如何实现跨平台的? 跨平台:一次编译,不需要任何代码修改,应用程序就可以运行在任 ...

  4. Unity 引擎开始从 Mono 迁移到 .NET CoreCLR

    目录 ​编辑 ​编辑 现状 过去 过去,Unity 选择 Mono 未来 未来,Unity 选择 CoreCLR 现状 Unity 引擎开发团队宣布,他们已开始将 Unity 引擎运行时从 Mono ...

  5. 用Unity做游戏,你需要深入了解一下IL2CPP

    这次我们翻译了一篇Unity官方博客上的文章,原文题目为AN INTRODUCTION TO IL2CPP INTERNALS ,作者是从事Unity软件开发的Joshua Peterson.文章的看 ...

  6. IL2CPP 构建大小优化

    https://support.unity3d.com/hc/zh-cn/articles/208412186-IL2CPP-%E6%9E%84%E5%BB%BA%E5%A4%A7%E5%B0%8F% ...

  7. [原创]安卓U3D逆向从Assembly-CSharp到il2cpp

    https://bbs.pediy.com/thread-223467.htm 随着unity技术的发展及厂商对于脚本源码的保护,很大一部分U3D应用的scripting backend已经由mono ...

  8. [IL2CPP] IL2CPP 减速(部分解决)

    英文原文: https://www.jacksondunstan.com/articles/3001   Unity 4.6.2 和 5.0 中的新 IL2CPP 脚本后端应该比旧的 Mono 后端快 ...

  9. Unity il2cpp API 调用实践

    测试环境 Unity2019.4.38 il2cpp版本24.5 c# to il to cpp 在Unity4.6.1 p5以后版本中,在PlayerSettings->Other Setti ...

最新文章

  1. mysql update 并发 慢_MySQL跑在CentOS 6 和 7上的性能比较
  2. 微信小程序自定义弹出框组件,模拟wx.showModal
  3. 2.8 使用开源的实现方案-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  4. ECshop商城程序常见的96个小问题汇总
  5. 去除字符串中的指定字符
  6. linux学习wdlinux学堂
  7. Google的YSlow——Page Speed(附插件下载)
  8. c++ 多个字符串排序_RPython Data Science系列:数据处理(5)--字符串函数基于R(一)
  9. 记一次Mysql数据库Kill完之后启动不起来的解决方案
  10. 投资理财web后端系统_银行理财产品有风险吗?最大风险是什么?
  11. NOIP 2016 游记
  12. 软考(一):迎战软考
  13. 100个WordPress常用插件精选
  14. 20172324 2018-2019-1 《程序设计与数据结构》第三周学习总结
  15. 致远OA表单自定义函数(明细表排名 )
  16. CUDA和TensorRT入门
  17. 道不投不足与谋:(,决定放弃原来的博客空间,不再更新
  18. KSO-.NETCore中实现跨域的代码以及几种跨域方式
  19. [激光原理与应用-41]:《光电检测技术-8》- 白光干涉仪
  20. 【python数据可视化笔记】——matplotlib.pyplot()

热门文章

  1. 要是我考上北大了.........
  2. 追风筝的人:变质的友谊
  3. 钉钉小程序源代码管理
  4. python 异常点检测 cook距离_异常检测算法汇总
  5. matlab之ones函数和zeros函数
  6. 操作系统--并发和并行
  7. java上传图片损坏_iview 文件上传二进制文件提示文件已经损坏
  8. HP大中华区总裁孙振耀谈工作和人生
  9. 将EXCEL表格转换成CAD表格的完整代码
  10. GPT-4,它来了!