Aci*_*dic 4 c# compiler-construction jit inline
由于这些属性只是方法之下,可以理解的是,它们可能执行的任何逻辑的性能可能会或可能不会提高性能 - 因此JIT需要检查方法是否值得内联是可以理解的.
然而,自动属性(据我所知)不能有任何逻辑,只需返回或设置基础字段的值.据我所知,自动属性由编译器和JIT处理,就像任何其他方法一样.
(以下所有内容都依赖于上述段落正确的假设.)
值类型属性显示与变量本身不同的行为,但是参考类型属性应该具有与直接访问基础变量完全相同的行为.
// Automatic Properties Example
public Object MyObj { get; private set; }
Run Code Online (Sandbox Code Playgroud)
是否存在自动属性Reference Types
可以通过内联显示性能受损的情况?
如果没有,是什么阻止编译器或JIT自动内联它们?
注意:我理解性能增益可能是微不足道的,特别是当JIT可能无论如何使用它时都可能内联它们 - 但是增益可能很小,似乎合乎逻辑的是,无论如何都会引入这种看似简单的优化.
编辑:JIT编译器不能像你想象的那样工作,我想这就是为什么你可能不完全理解我试图在上面传达的内容.我在下面引用了你的评论:
这是一个不同的问题,但据我所知,只有在被调用足够次数的情况下,方法才会被检查为内联值.没有提到检查本身就是性能损失.(现在,让性能影响的大小无关紧要.)
首先,检查大多数(如果不是全部)方法以查看它们是否可以内联.其次,保持该方法只有永远JIT编译的一次头脑,它是在一个时间,该JITer将确定是否有任何调用的方法中的,将被内联.这可能在您的程序执行任何代码之前发生.什么使被调用的方法成为内联的良好候选者?
x86 JIT编译器(x64和ia64不一定使用相同的优化技术)检查一些事情以确定方法是否适合内联,绝对不仅仅是它被调用的次数. 本文列出了如果内联将使代码更小,如果调用站点将被执行很多次(即在循环中),以及其他内容.每个方法都是自己优化的,因此该方法可以在一个调用方法中内联,而在另一个调用方法中不内联,如在循环的示例中.这些优化启发式只适用于JIT,C#编译器只是不知道:它产生的是IL,而不是本机代码.他们之间有很大的不同; native vs IL代码大小可能完全不同.
总而言之,出于性能原因,C#编译器不会内联属性.
jit编译器内联大多数简单属性,包括自动属性.您可以在这篇有趣的博客文章中阅读有关JIT如何决定内联方法调用的更多信息.
好吧,C#编译器根本没有内联任何方法.我认为这是因为CLR的设计方式.每个组件都设计为可在机器之间移动.很多时候,您可以更改.NET程序集的内部行为而无需重新编译所有代码,它可以只是替换(至少在类型没有更改时).如果代码是内联的,它会破坏(伟大的,imo)设计并且你失去了光彩.
我们先来谈谈C++中的内联.(完全披露,我有一段时间没有使用C++全职,所以我可能会模糊,我的解释生锈,或完全不正确!我指望我的同伴SOers纠正并骂我)
C++ inline关键字就像告诉编译器,"嘿,伙计,我希望你能够内联这个函数,因为我认为它会提高性能". 联合国幸运的是,它只是告诉你宁愿它内联的编译器; 它没有告诉它必须.
也许在较早的日期,当编译器的优化程度低于现在时,编译器通常会编译内联函数.然而,随着时间的推移和编译器变得越来越聪明,编译器编写者发现在大多数情况下,他们更擅长确定何时应该将开发人员的内联函数.对于那些没有的情况,开发人员可以使用seriouslybro_inlineme
关键字(__forceinline
在VC++中正式调用).
现在,为什么编译器编写者会这样做?好吧,内联函数并不总是意味着提高性能.虽然它确实可以,但如果使用不当,它也会破坏您的程序性能.例如,我们都知道内联代码的一个副作用是增加代码大小,或"胖代码综合症"(免责声明:不是真正的术语).为什么"胖码综合症"成了问题?如果你看看我上面链接的文章,它解释了,除其他外,内存很慢,代码越大,它在最快的CPU缓存(L1)中的可能性就越小.最终它只能适合内存,然后,内联没有做任何事情.但是,编译器知道这些情况何时会发生,并尽力防止它.
把它与你的问题放在一起,让我们这样看:C#编译器就像是为JIT编译器编写代码的开发人员:JIT更聪明(但不是天才).它通常知道内联何时会有利于或损害执行速度."高级开发人员"C#编译器不知道如何内联方法调用可以使代码的运行时执行受益,所以它不会.我想这实际上意味着C#编译器很聪明,因为它将优化工作留给了那些比它好的人,在本例中是JIT编译器.