JIT编译器是否优化(内联)不必要的变量声明

本文关键字:不必要 变量 声明 内联 编译器 是否 优化 JIT | 更新日期: 2023-09-27 18:11:59

我读了几篇文章和问答,得出的结论是,最佳实践是让JIT编译器完成内联函数调用的所有优化。是有意义的。

内联变量声明呢?编译器是否也对这些进行了优化?

即:

        Dim h = (a + b + c) / 2       'Half-Perimeter
        If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then
           'Do stuff here.
        End If

有比这更好的性能:

        Dim perimeter = a + b + c   'Perimeter
        Dim h = perimeter / 2       'Half-Perimeter
        Dim area = Math.Sqrt(h * (h - a) * (h - b) * (h - c)) 'Heron's forumula.
        Dim inradius = area / h
        Dim aspectRatio = maxEdgeLength / inradius
        If aspectRatio <= MaximumTriangleAspectRatio Then
            'Do stuff here.
        End If

当然,我更喜欢后者,因为它更容易阅读和调试,但如果它存在,我无法承受性能下降。

注意:我已经将这段代码确定为瓶颈——不需要对过早优化进行反驳。: -)

JIT编译器是否优化(内联)不必要的变量声明

临时变量是否有名称是无关紧要的。

但是你可以显著优化这个不等式。

你的代码是:

If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then

两边同时乘以平方根,去掉除法(不等式保留,因为平方根不能返回负数):

If maxEdgeLength <= (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) * MaximumTriangleAspectRatio Then

现在,两边同时平方以消除昂贵的平方根:

If maxEdgeLength * maxEdgeLength <= h * (h - a) * (h - b) * (h - c) / h / h * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

消去,乘以h

If maxEdgeLength * maxEdgeLength * h <= (h - a) * (h - b) * (h - c) * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

这样会快很多。如果重复此计算,请考虑缓存该表达式的部分结果,以获得更大的改进。

使用注释来解释公式。在瓶颈函数中摆脱Math.Sqrt调用是值得用一种不那么简单的格式来编写表达式的。

顺便说一下,为了唱反调,我还想指出这一点:

整个函数的JIT内联关注的是MSIL的字节长度,而不是计算的复杂性。添加局部变量(并期望JIT注册它们)可能会增加函数的MSIL大小,足以使整个函数不适合内联。

这不太可能产生像不必要使用Math.Sqrt那样大的差异,但这是一种可能性。正如Eric Lippert所说,通过实际测量你会知道更多。然而,这样的度量只对程序的一个特定运行有效,而不能推广到不同的处理器或. net运行时的未来版本(包括服务包),因为它们经常调整JIT行为。所以你需要一个结合分析和经验的方法来优化。