C# 编译器是否足够智能来优化此代码? [英] Is the C# compiler smart enough to optimize this code?

查看:21
本文介绍了C# 编译器是否足够智能来优化此代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请忽略此问题中的代码可读性.

Please ignore code readability in this question.

从性能上来说,下面的代码应该是这样写的:

In terms of performance, should the following code be written like this:

int maxResults = criteria.MaxResults;

if (maxResults > 0)
{
    while (accounts.Count > maxResults)
        accounts.RemoveAt(maxResults);
}

或者像这样:

if (criteria.MaxResults > 0)
{
    while (accounts.Count > criteria.MaxResults)
        accounts.RemoveAt(criteria.MaxResults);
}

?

criteria 是一个 classMaxResults 是一个简单的整数属性(即,public int MaxResults { get {返回_maxResults; } }.

criteria is a class, and MaxResults is a simple integer property (i.e., public int MaxResults { get { return _maxResults; } }.

C# 编译器是否将 MaxResults 视为黑盒并每次都对其进行评估?或者它是否足够聪明,可以确定我有 3 个对同一属性的调用,而在两次调用之间没有修改该属性?如果 MaxResults 是一个字段会怎样?

Does the C# compiler treat MaxResults as a black box and evaluate it every time? Or is it smart enough to figure out that I've got 3 calls to the same property with no modification of that property between the calls? What if MaxResults was a field?

优化的一个规律是预先计算,所以我像第一个清单一样本能地编写了这段代码,但我很好奇这种事情是否为我自动完成(再次忽略代码可读性).

One of the laws of optimization is precalculation, so I instinctively wrote this code like the first listing, but I'm curious if this kind of thing is being done for me automatically (again, ignore code readability).

(注意:我对听到微优化"的论点不感兴趣,这在我发布的特定案例中可能是有效的.我只想了解正在发生或未发生的事情背后的一些理论.)

(Note: I'm not interested in hearing the 'micro-optimization' argument, which may be valid in the specific case I've posted. I'd just like some theory behind what's going on or not going on.)

推荐答案

首先,真正回答性能问题的唯一方法是实际尝试两种方法并在现实条件下测试结果.

First off, the only way to actually answer performance questions is to actually try it both ways and test the results in realistic conditions.

也就是说,其他答案说编译器"不进行这种优化,因为该属性可能有副作用,这是对的也是错的.这个问题的问题(除了基本问题之外,如果不实际尝试并测量结果就无法回答)是编译器"实际上是两个编译器:C# 编译器,它编译为 MSIL,和 JIT 编译器, 将 IL 编译为机器代码.

That said, the other answers which say that "the compiler" does not do this optimization because the property might have side effects are both right and wrong. The problem with the question (aside from the fundamental problem that it simply cannot be answered without actually trying it and measuring the result) is that "the compiler" is actually two compilers: the C# compiler, which compiles to MSIL, and the JIT compiler, which compiles IL to machine code.

C# 编译器从来没有做过这种优化;如前所述,这样做需要编译器查看被调用的代码并验证它计算的结果在被调用者代码的生命周期内不会改变.C# 编译器不会这样做.

The C# compiler never ever does this sort of optimization; as noted, doing so would require that the compiler peer into the code being called and verify that the result it computes does not change over the lifetime of the callee's code. The C# compiler does not do so.

JIT 编译器可能会.没有理由不能.它有所有的代码就在那里.内联属性 getter 是完全自由的,如果抖动确定内联的属性 getter 返回一个可以缓存在寄存器中并重新使用的值,那么它可以自由地这样做.(如果您不希望它这样做,因为可以在另一个线程上修改该值,那么您已经存在竞争条件错误;在担心性能之前修复该错误.)

The JIT compiler might. No reason why it couldn't. It has all the code sitting right there. It is completely free to inline the property getter, and if the jitter determines that the inlined property getter returns a value that can be cached in a register and re-used, then it is free to do so. (If you don't want it to do so because the value could be modified on another thread then you already have a race condition bug; fix the bug before you worry about performance.)

抖动是否确实确实内联属性获取然后注册该值,我不知道.我对抖动几乎一无所知.但如果它认为合适,则允许这样做.如果您对它是否这样做感到好奇,您可以 (1) 询问编写抖动的团队中的某个人,或者 (2) 在调试器中检查抖动的代码.

Whether the jitter actually does inline the property fetch and then enregister the value, I have no idea. I know practically nothing about the jitter. But it is allowed to do so if it sees fit. If you are curious about whether it does so or not, you can either (1) ask someone who is on the team that wrote the jitter, or (2) examine the jitted code in the debugger.

最后,让我借此机会指出,一次计算结果、存储结果并重新使用它并不总是一种优化.这是一个令人惊讶的复杂问题.有各种各样的东西需要优化:

And finally, let me take this opportunity to note that computing results once, storing the result and re-using it is not always an optimization. This is a surprisingly complicated question. There are all kinds of things to optimize for:

  • 执行时间

  • execution time

可执行代码大小——这对可执行时间有重大影响,因为大代码需要更长的时间来加载,增加工作集大小,给处理器缓存、RAM 和页面文件带来压力.从长远来看,在启动时间和缓存位置等重要指标方面,小的慢代码通常比大的快代码要快.

executable code size -- this has a major effect on executable time because big code takes longer to load, increases the working set size, puts pressure on processor caches, RAM and the page file. Small slow code is often in the long run faster than big fast code in important metrics like startup time and cache locality.

寄存器分配——这也对执行时间有重大影响,特别是在像 x86 这样的架构中,可用寄存器的数量很少.注册一个值以进行快速重用可能意味着可用于其他需要优化的操作的寄存器较少;或许优化这些操作反而会取得胜利.

register allocation -- this also has a major effect on execution time, particularly in architectures like x86 which have a small number of available registers. Enregistering a value for fast re-use can mean that there are fewer registers available for other operations that need optimization; perhaps optimizing those operations instead would be a net win.

等等.它变得非常复杂,非常快.

and so on. It get real complicated real fast.

简而言之,您不可能知道编写代码来缓存结果而不是重新计算它实际上是 (1) 更快,还是 (2) 性能更好.更好的性能并不总是意味着更快地执行特定例程.更好的性能是关于弄清楚哪些资源对用户很重要——执行时间、内存、工作集、启动时间等等- 并针对这些事情进行优化.如果没有 (1) 与客户交谈以了解他们关心什么,以及 (2) 实际衡量以查看您的更改是否在所需方向上产生了可衡量的效果,您就无法做到这一点.

In short, you cannot possibly know whether writing the code to cache the result rather than recomputing it is actually (1) faster, or (2) better performing. Better performance does not always mean making execution of a particular routine faster. Better performance is about figuring out what resources are important to the user -- execution time, memory, working set, startup time, and so on -- and optimizing for those things. You cannot do that without (1) talking to your customers to find out what they care about, and (2) actually measuring to see if your changes are having a measurable effect in the desired direction.

这篇关于C# 编译器是否足够智能来优化此代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆