C# 方法慢 100 倍,三个返回比两个?

标签 c# performance optimization

当我尝试对其进行性能测试时,我使用的方法有一些奇怪的行为,基本上如果我注释掉/禁用其中一个 if 语句中的一个返回值,它会从 400 毫秒变为 4 毫秒,几乎就像它被编译掉了,而不是实际运行代码,如果在评论/禁用一个返回后,它只返回真或假,那么它只有一个选项,那么我可以看到编译器如何将优化它并始终​​将其设置为 bool 值而不是运行代码。

任何人都知道可能会发生什么或对运行测试的更好方法有建议吗?

我的测试代码:

Vec3 spherePos = new Vec3(43.7527, 75.9756, 0);
double sphereRadisSq = 50 * 50;
Vec3 rayPos = new Vec3(-5.32301, 5.97157, -112.983);
Vec3 rayDir = new Vec3(0.457841, 0.680324, 0.572312);

sw.Reset();
sw.Start();
bool res = false;
for (int i = 0; i < 10000000; i++)
{
   res = Intersect.RaySphereFast(rayPos, rayDir, spherePos, sphereRadisSq);
}      
sw.Stop();
Debug.Log($"testTime: {sw.ElapsedMilliseconds} ms");
Debug.Log(res);

和静态方法:

public static bool RaySphereFast(Vec3 _rp, Vec3 _rd, Vec3 _sp, double _srsq) 
{
    double rs = Vec3.DistanceFast(_rp, _sp);
    if (rs < _srsq)
    {
        return (true); // <-- When I disable this one
    }
    Vec3 p = Vec3.ProjectFast(_sp, _rp, _rd);
    double pr = Vec3.Dot(_rd, (p - _rp));
    if (pr < 0)
    {
        return (false); // <--  Or when I disable this one
    }
    double ps = Vec3.DistanceFast(p, _sp);
    if (ps < _srsq) 
    {
        return (true); // <--  Or when I disable this one
    }
    return (false);
}

Vec3 结构(精简):

public struct Vec3
{
    public Vec3(double _x, double _y, double _z)
    {
        x = _x;
        y = _y;
        z = _z;
    }

    public double x { get; }
    public double y { get; }
    public double z { get; }

    public static double DistanceFast(Vec3 _v0, Vec3 _v1) 
    {
        double x = (_v1.x - _v0.x);
        double y = (_v1.y - _v0.y);
        double z = (_v1.z - _v0.z);
        return ((x * x) + (y * y) + (z * z));
    }

    public static double Dot(Vec3 _v0, Vec3 _v1)
    {
        return ((_v0.x * _v1.x) + (_v0.y * _v1.y) + (_v0.z * _v1.z));
    }

    public static Vec3 ProjectFast(Vec3 _p, Vec3 _a, Vec3 _d) 
    {
        Vec3 ap = _p - _a;
        return (_a + Vec3.Dot(ap, _d) * _d);
    }

    public static Vec3 operator +(Vec3 _v0, Vec3 _v1)
    {
        return (new Vec3(_v0.x + _v1.x, _v0.y + _v1.y, _v0.z + _v1.z));
    }

    public static Vec3 operator -(Vec3 _v0, Vec3 _v1)
    {
        return new Vec3(_v0.x - _v1.x, _v0.y - _v1.y, _v0.z - _v1.z);
    }

    public static Vec3 operator *(double _d1, Vec3 _v0)
    {
        return new Vec3(_d1 * _v0.x, _d1 * _v0.y, _d1 * _v0.z);
    }
}

最佳答案

这很可能会发生,因为当您注释掉返回值时,方法的复杂性会低于禁用自动内联的阈值。

此内联在生成的 IL 中不可见 - 它由 JIT 编译器完成。

我们可以通过用 [MethodImpl(MethodImplOptions.AggressiveInlining)] 属性修饰相关方法来检验这个假设。

当我使用您的代码尝试此操作时,我获得了以下结果(发布,x64 构建):

Original code:                      302 ms
First return commented out:           2 ms
Decorated with AggressiveInlining:    2 ms

注释掉第一个返回的时间与我用 AggressiveInlining 装饰方法时获得的时间相同(启用第一个返回)。

因此我断定假设是正确的。

关于C# 方法慢 100 倍,三个返回比两个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52242001/

相关文章:

c# - FluentValidation 验证枚举值

c# - asp.net mvc 4,线程被模型绑定(bind)改变了吗?

mysql 使用子查询改进 View

sql - 使用范围索引查询 Sql 服务器

java - 求和文本文件中整数的最快方法

c# - 如何在 Outlook 中创建日历组文件夹?

c# - HttpContext.Current.User 和 HttpContext.User 有什么区别

java - mysql jdbc 驱动程序类是否知道批量执行多个插入?

python - 优化Python字典/负索引存储

optimization - 解决 3d 多边形网格的最佳对齐问题