网站开发用户需求广西施工员证书查询

bicheng/2026/1/19 1:24:32/文章来源:
网站开发用户需求,广西施工员证书查询,seo是什么牌子,招生网站建设策划方案最近在研究Unity il2cpp的代码生成和编译优化#xff0c;结合之前遇到过的一个优化案例#xff0c;给大家讲讲在Unity中迭代器相关代码生成的底层原理#xff0c;以及在写代码过程中需要注意的一些特殊情况。 案例 首先我们来看一个非常简单的案例#xff0c;代码如下结合之前遇到过的一个优化案例给大家讲讲在Unity中迭代器相关代码生成的底层原理以及在写代码过程中需要注意的一些特殊情况。 案例 首先我们来看一个非常简单的案例代码如下 public class NewBehaviourScript : MonoBehaviour {private Listfloat _objects new Listfloat();private float GetSumSlow(IEnumerablefloat arr) {float sum 0;foreach (var value in arr) {sum value;}return sum;}void Start() {for (int i 0; i 100000; i) {_objects.Add(0.1f);}}void Update() {float sum GetSumSlow(_objects);} }其中重点来看 GetSumSlow 这个函数的逻辑就是使用迭代器遍历一个集合计算元素之和代码乍看起来也没有什么问题。但是当我们使用 VTune 去抓数据的时候会发现正是这个很简单的函数出现了问题在函数耗时TOP的前几名都能看到好几个和这个迭代器相关的函数甚至在某些情况下还会因为较多的 Cache Miss 引起 Memory Bound 问题。 从代码逻辑来看这个函数内部其实做一件非常简单而常见的事情并且访问的内存也是连续的理论来看并不应该会引起任何性能问题但通过详细分析了Unity il2cpp代码生成逻辑以后我们通过修改了其中一行代码修改后如下 private float GetSumFast(Listfloat arr) { // 只修改这一行float sum 0;foreach (var value in arr) {sum value;}return sum; }其中我们仅仅是将函数的参数类型从 IEnumerable 接口类型修改成了具体的实现类型List然后我们再使用 VTune 去对比数据惊奇的发现该函数的CPU耗时大幅度的减少性能居然大幅的提升了 5 倍左右对比数据如下 这个案例很小但足够有趣因此接下来我们就用这个案例作为引子来简单聊聊 il2cpp 的代码生成和编译优化的一整套流程并随着这个过程我们来解答这个案例的谜底。 ​ il2cpp 对于 il2cpp 大家都比较熟悉它相对的概念是早期的 mono 虚拟机Unity游戏的开发使用是 C# 语言在 il2cpp 模式下会将 C# 语言翻译成 C 在用户的机器上运行其运行的效率和安全性相比于早期的 mono 是有大幅提升的我们这里主要关注从你写的 C# 代码是如何一步一步的转换成 C 代码并最终运行在用户的机器上的。 首先Unity通过如下流程从 C# 转成 C 代码 然后使用本机的 C 的编译器转成机器码这里以 Android 平台为例 在这整个流程中其实比较特殊的只有两个环节 UnityLinker, Unity在 C# 的 IL Linker 的基础上实现的一个专门处理 Assembly 文件的 Linker这里的 Linker 类似于 gcc/clang 等编译器相关的 linker它主要负责在编译环节将相关的模块链接到一起但是 Unity 为了实现 il2cpp 还需要在这个 Linker 之上实现一个最重要的 C# 模块/代码剔除的功能因为一般 C# 代码都会有很多运行时库和第三方库的依赖而如果原封不动的将所有的这些DLL里面的C#代码都转成 C那么最后在编译 C 代码 的时候就连 LLVM 都会因为其代码量之大需要编译非常久的时间甚至还可能超过 linker 的上限而无法编译成功因此 UnityLinker 需要去分析各个 Assembly 的依赖关系将不需要的DLL剔除出去甚至它还需要去分析其中的 C# 函数和函数之间的调用关系将DLL中不需要的代码给完全剔除出去使其只将需要的精简的 C# 代码在下一个阶段转换为 C 代码。 il2cpp, 它是Unity中用 C# 实现的一个二进制程序它主要负责将 Assembly 文件中的 IL 指令一条一条的翻译成 C 代码这个翻译的过程比较机械和枯燥但我们可以用一个比较简单的方式来理解它那就是这个 il2cpp 编译器或者叫翻译器的主要逻辑和之前 mono 虚拟机的实现逻辑是差不多的流程mono虚拟机内有一个很大很大的 switch 语句它负责处理每一条 IL 指令 将它们在运行时立即执行而 il2cpp 编译器的逻辑也是类似的它只是在离线的状态下去模拟一个IL虚拟机最主要的区别是它在处理每一条 IL 指令时不是立即执行而是将该条指令翻译成 C 的代码纯文本形式并且为了支持这种1对1的机械性翻译以及C#的动态语言的要求它需要非常多的生成代码和一个非常强大的 il2cpp runtime 来作为这些指令翻译代码的支撑。 下面我们还是以上一节案例中提到的 GetSum 函数来作例子说明例如有如下的 C# 代码 public class NewBehaviourScript2 : MonoBehaviour {private Listfloat _objects new Listfloat();private float GetSumSlow(IEnumerablefloat arr) {float sum 0;foreach (var value in arr) {sum value;}return sum;} }这里通过 il2cpp 会翻译成如下的 C 代码因为它翻译的 C 代码不宜人去读因此这里我人工精简了一下 struct NewBehaviourScript2 : public MonoBehaviour {List_1* objects; };float NewBehaviourScript2_GetSumSlow(NewBehaviourScript2* this, RuntimeObject* arr, const RuntimeMethod* method) {float sum 0.0f;// System.Collections.Generic.IEnumerable1System.Single::GetEnumerator()RuntimeObject* enumerator InterfaceFuncInvoker0RuntimeObject*::Invoke(0, IEnumerable_1_il2cpp_TypeInfo_var, arr);while (true) {// System.Collections.Generic.IEnumerator1System.Single::get_Current()float cur InterfaceFuncInvoker0float::Invoke(0, IEnumerable_1_il2cpp_TypeInfo_var, enumerator);sum cur;// System.Boolean System.Collections.IEnumerator::MoveNext()bool has_next InterfaceFuncInvoker0 bool ::Invoke(0, IEnumerable_1_il2cpp_TypeInfo_var, enumerator);if (!has_next) {break;}}return sum; }我们通过 C# 代码和生成的 C 代码对比可以发现 il2cpp 的几个特点 C# 里面的 class 的定义会被翻译成 C 里面的 struct。C# class里面的成员变量都会转化成 C 结构体里面的成员。C# class里面的成员方法都会转成独立的 C 函数并且第一个参数为 this 指针。 这里我们看到它虽然叫自己 il2cpp 但是其还是将 C# class 翻译成了C风格的面向对象的代码。另外我们也可以看出来 C# 里面的 foreach 有点类似语法糖的感觉其内部实现还是通过调用 C#迭代器IEnumerable  IEnumerator来实现的。因为 il2cpp 并不是直接将 C# 源码 转成 C 源码而是先用 mcs 编译器将 C# 源码编译成 IL 指令然后再将 IL指令 转成为 C 源码的因此我们这里直接对比 C# 和 C 代码中间就会出现一些跳跃所以这里我们可以来观察一下 C# 源码编译后的 IL 指令和转换后的 C源码就更加一目了然了 il2cpp 编译器在翻译的时候就是从下往下依次遍历这些 IL 指令例如 callvirt IL指令表示调用一个虚函数而对应翻译出来的 C 代码为 InterfaceFuncInvoker0::Invoke()add IL指令表示加法运行对应翻译出来的 C 代码为 ilc2pp_codegen_add() 这里对照着看就能看出来我们之前提过的il2cpp 将 IL指令翻译成 C 代码是很机械的它几乎就是1条1条的硬翻而为了满足这种简单的翻译逻辑il2cpp 需要提供很多生成的函数以及一个强大的运行时来作为支撑例如这里简单的一个 add 指令它无法将其直接翻译成加法的机器指令而是翻译成了一个函数调用再在调用的这个生成函数里面取做加法运算也正是因为这种比较笨拙的方法导致了 il2cpp 翻译出 C 代码即使经过了 llvm 这种优秀的编译器优化后依然存在一些冗余的不必要的消耗虽然Unity在生成C代码的时候已经引入了很多编译器代码优化的技巧来尽量使其翻译的代码更加高效但毕竟和人直接写出来的C代码在运行效率的质量上还是不能比的。 ​ 这里我们可以详细来分析一下它生成的C代码明明我们写的 C#代码 想做的事情很简单很朴素就是遍历一个连续内存空间的集合计算其元素的值之和。但是在经过 il2cpp 翻译成C代码后我们看了至少N个看似很多余的虚函数调用在遍历整个集合的过程中每次迭代都需要先查找2个虚函数的地址先调用get_Current() 虚函数获取当前元素的值然后调用 MoveNext() 虚函数迭代到下一个元素继续遍历。 ​ 我们也可以看看 il2cpp 生成的虚函数调用的代码实现 template typename R struct InterfaceFuncInvoker0 {typedef R (*Func)(void*, const RuntimeMethod*);static inline R Invoke (Il2CppMethodSlot slot, RuntimeClass* declaringInterface, RuntimeObject* obj){const VirtualInvokeData invokeData il2cpp_codegen_get_interface_invoke_data(slot, obj, declaringInterface);return ((Func)invokeData.methodPtr)(obj, invokeData.method);} };它在调用虚函数之前必须先调用另一个函数来找到这个虚函数的指针地址而每次遍历的时候这个重复的操作都需要进行增加了很多不必要的消耗。 ​ 我们再来看 VTune 的数据 我们可以明显从数据中看到CPU耗时TOP前面几名的函数都是由于 il2cpp 生成的这些查找和调用虚函数的代码因为它生成的 C# 的class 并不是 C 的class编译器并没有生成 C 类的虚表而是自己实现和管理了每个类的 C 风格的 vtable 它在遍历集合时每一次迭代中都需要重复去查找这些虚函数的地址这些函数时间的耗时甚至都超过了 for 循环里面业务逻辑的耗时这些消耗并不是程序员写的 C# 业务代码带来的直接消耗而是 il2cpp 生成代码带来的额外消耗。 ​ 优化 当我们分析了一整套 il2cpp 的代码生成逻辑就明白了为什么一个简单的迭代器和for循环会带来这么多额外CPU耗时我们无法改变 il2cpp 的代码生成逻辑但在理解了它的内部逻辑后我们依然可以在写C#代码的时候带着这些对于 il2cpp 的内部实现的理解来避免一些不必要的消耗。 例如在这里案例中我们已经知道了在使用迭代器中最需要被优化掉的消耗应该是那几个虚函数的调用正常人在for循环中都不会写出这样低效的代码如果我们需要优化这些的代码有几个思路 不要在for循环里面调用函数主要优化手段就是 inline 。如果非要调用函数也尽量让它是一个直接的函数调用而不是一个虚函数的间接调用要先查询函数地址再调用函数。 这里我们已经知道问题的关键在于 IL 中的 callvirt 指令我们需要把这个指令优化成一个 call 的指令因此我们最直接的修改办法就是避免向上转型将这个函数的参数类型从 IEnumerable 接口类型修改成了具体的实现类型List我们来看修改后的 IL 指令 这里我们看到两个很重要的区别 首先在 IL指令 callvirt 指令可以被我们优化成 call 的指令从而避免了虚函数的调用。然后我们调用的函数是一个 inline 函数Unity已经在帮我们做了优化因此在for循环中又少了1次函数调用的消耗当你的集合比较大并且每帧又需要频繁去遍历的时候在for循环中少1次函数调用也能明显提升这个函数的性能。 下面我们把这两个函数同时编译进去并用 VTune 进行对比 这里可以明显看到几点区别 优化之前的函数在遍历的时候调用了很多其他函数并且整体CPU耗时都基本浪费在调用的这些子函数上函数自身耗时并不大。优化之后的函数在遍历的时候只调用了1个函数并且整体CPU耗时明显要少了很多倍。 ​ 最后我们总结发现其实只花了相对很少的时间对于Unity il2cpp底层的实现原理多了一点点的了解我们就能精准的通过仅仅修改了一行代码就让其函数性能提升了整整5倍之多这种性价比是非常高的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/89020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站设计的主题顺德网络营销网站

Linux C 022-函数模板 本节关键字:Linux、C、函数模板、泛型编程 相关库函数: 函数模板的用法 C另一种编程思想称为泛型编程,主要利用的技术就是模板,C提供两种模板机制:函数模板和类模板函数模板的作用&#xff1a…

学校网站栏目建设哪里公司建设网站好

1.变量和字面量(常量) 字面量就是一个一个的值,比如:1,2,3,4,5,6,‘HELLO’ 字面量所表示的意思就是它的字面的值,在程序中可以直接使用字面量 变量(varia…

安徽省建设工程信息网站深圳网深圳网站开发公司

W...Y的主页😊 代码仓库分享💕 ​ 🍔前言: 今天我们正式进入C篇章,作为学过C语言的同志,继续学习C肯定就不会进行那些与C语言相同的学习,因为C语言的内容在C中也可以正常使用,所…

义乌企业网站设计网上销售怎样做网站

放映笔 幻灯片放映时,工具在幻灯片的左下方,本工具在幻灯片的右侧,可以移动,可以方便在右侧讲课时候使用 绘图板 可在绘图板上写签名、绘制图画、写字等等,点画笔切换橡皮擦,点插入绘图,将背景…

做外贸用什么网站比较好西安建筑科技大学就业信息网

一.基本分类 1.单变量的传统时间序列分析 2.单变量的随机时间序列分析 3.多变量的时间序列分析 建立在回归基础上的两变量序列分析 建立在AR基础上的多变量序列分析 4.截面时序数据结合的分析 转载于:https://www.cnblogs.com/xyp666/p/9220667.html

建设网站的主要任务wordpress优化主题

文章目录 1. 线程互斥1.1 问题引入1.2 线程互斥的相关概念1.3 互斥量mutex1.4 互斥量实现原理1.5 死锁 2. 线程安全和可重入函数3. 线程同步3.1 同步概念3.2 条件变量 4. 生产消费模型4.1 基于阻塞队列的cp模型4.2 基于环形队列的cp模型POSIX信号量 5. 线程池5.1 互斥量RAII版本…

自己建设网站需要多少钱做商品条形码的网站

抖音直播招聘报白是指企业人力资源公司在抖音进行直播招聘时,需要向抖音平台提供审核申请。通过报白,企业或人力资源公司可以更好的获取招聘渠道和更多曝光的机会,同时可以提升品牌形象和知名度。报白的对象针对需要企业自招的企业和人力资源…

用二级域名做网站群浏览器网站设置在哪里

声明式管理方(yaml)文件: 1、适合对资源的修改操作 2、声明式管理依赖于yaml文件,所有的内容都在yaml文件当中。 3、编辑好的yaml文件需要依靠陈述是还是要依靠陈述式的命令发布到k8s集群当中 create只能创建,不能更新。从指定yaml文件中读取配置&#…

移动端网站设计尺寸免费自助开通网站

学习计划:初学者到高手 第1-2周:基础入门 目标:了解Shell脚本的基本概念,掌握基础命令。内容: Shell脚本是什么,为什么使用Shell脚本。基本的Shell命令(如ls, cd, mkdir, rm等)。简…

网站建设 培训 南充google搜索关键词热度

线程管理 线程管理相关概念什么是时间片轮转调度器锁线程运行机制线程的五种状态 动态和静态创建线程区别动态和静态创建线程优缺点RT-Thread动态线程管理函数动态创建线程动态删除线程 RT-Thread静态线程管理函数静态创建线程 线程其他操作线程启动线程延时获得当前执行的线程…

门户手机网站模板做网站虚拟主机和云服务器吗

这种题对于我来说只能看大佬的wp(但是这一题是wp都看不懂,只能表达一下我的理解了) (最后有简单方法,前面一种没看懂没关系) 下面这一部分是首页的有用部分 访问/source_code,得到源码: # -*-…

徐州企业网站设计wordpress修改上传附件大小

(图片来源于网络)几天前,本公众号发布的一篇译文列举了9种DevOps团队结构适用类型与7种反型(点击查看原文)。文章转发到朋友圈之后,很多DevOps同行留言(吐槽)了自己团队的现状&#…

c2c电子商务网站建设栏目结构图网站建设专家

原文作者:我辈李想 版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、数据库层面优化常用优化postgresql查询分库分表 二、内存层面优化三、代码层面优化 前言 Django是一个高级的Web框架,它…

绿色农产品网站企业服务账号

本文会介绍 1个 POD 从启动到被关闭删除, 有什么事情发生, 和有什么组件被参与进来 容器环境初始化阶段 apiserver 接受到创建容器的指令时, 在构建容器之前会有一些环境的设置阶段, 例如node 选择, image 镜像下载等…

湖南网站定制建立一个公司自己的网站

文章目录 前言声明一、Panalog大数据日志审计系统简介二、漏洞描述三、影响版本四、漏洞复现五、整改意见 前言 Panalog大数据日志审计系统定位于将大数据产品应用于高校、 公安、 政企、 医疗、 金融、 能源等行业之中,针对网络流量的信息进行日志留存&#xff0c…

订阅号怎么做免费的视频网站吗公司网站建设知乎

听课问题 除了读未提交,有一个事务对一条数据进行了修改,但是另外又有一个没有加事务的查询sql,那么读取到的数据是原始数据还是没提交的数据。 答案:没加事务的查询读取的是老数据,等事务提交以后就会读取新修改的数据 除了读…

网站的建设和品牌价值的关系wordpress二手房

刚刚在被大雨中断了两次的温网女单半决赛中,小威廉姆斯以2比0战胜了中国的郑洁。这是大块头对小女孩儿的比赛,是蛮牛与人的较力,是大猩猩与儿童的掰腕。在弱小的郑洁面前,小威确实太强悍了,她的大力正反手回球和扣球&a…

购物网站建设平台整站优化网站

文章目录 前言资源推荐环境如何开始Blazor个人推荐设置注释快捷键热重载设置 前言 Blazor简单来说就是微软提供的.NET 前端框架。使用 WebAssembly的“云浏览器”,集成了Vue,React,Angular等知名前端框架的特点。 资源推荐 微软官方文档 Blazor入门基础视频合集 …

国外电商网站建设西安知名的网站建设公司

偏系统化的ER图例子还是不够,需要寻找 汇报时很多人的er图都有问题,重点是作为e的实体(方框表示)含义并没有搞懂

建设网站的定位网站建成之后应该怎么做

Wireshark 、HTTPWatch、Fiddler的介绍 Firebug虽然可以抓包,但是对于分析http请求的详细信息,不够强大。模拟http请求的功能也不够,且firebug常常是需要“无刷新修改”,如果刷新了页面,所有的修改都不会保存。Wiresha…