当我们使用outref的内部计算,有多个作业(job)和阅读,它有什么缺点?这会影响表演吗?

static bool TrySomeFunction(int x, int y, out int result)
{
    result = 8;
    for (int i = 0; i < x; i++)
    {
        result += result + x;
        if (result == y)
            return false;
    }
    return true;
}

或者我们最好使用额外的变量:

static bool TrySomeFunction(int x, int y, out int result)
    {
        int temp = 8;
        for (int i = 0; i < x; i++)
        {
            temp += temp + x;
            if (temp == y)
            {
                result = 0;
                return false;
            }      
        }
        result = temp;
        return true;
    }

更新:将函数名从SomeFunction更改为更清晰的预期用途.

推荐答案

事实证明,我们做的计算越多,两者的性能差异就越大.

我相信这是意料之中的,因为这里我们看到了一个额外的间接层次.ldindstind操作用于获取/设置out参数的值(间接),ldocstloc操作用于获取/设置局部变量的值.

我认为编译器不能在这里进行任何优化(至少将UseOutExtensively转换为DontUseOutExtensively),因为如果其他线程在执行函数的同时写入out参数的位置,这可能会改变方法的行为.

测验

让我稍微简化一下您的函数,以便我们只关注我们感兴趣的内容:

void UseOutExtensively(out int result)
{
    result = 0;
    for (int i = 0; i < 100; i++)
    {
        int temp = result;
        result = temp;
    }
}

void DontUseOutExtensively(out int result)
{
    int temp = 8;
    for (int i = 0; i < 100; i++)
    {
        int anotherTemp = temp;
        temp = anotherTemp;
    }
    result = temp;
}

所以函数没有做任何有用的事情,它们只是在变量之间交换相同的值.因此,我们没有复杂的加法和条件,只需要获取/设置一个out变量和获取/设置一个局部变量.

因此,测试程序如下所示:

int Iterations = 10000000; // we'll try 10^7, 10^8 && 10^9

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
  UseOutExtensively(out int result);

Console.WriteLine("Using out extensively: {0}",
                          sw.ElapsedMilliseconds);

sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
  DontUseOutExtensively(out int result);

Console.WriteLine("Don't use out extensively: {0}",
                          sw.ElapsedMilliseconds);

结果:

Iterations UseOutExtensively DontUseOutExtensively
10^7 918 330
10^8 8850 3331
10^9 92009 34823

我们看到我们执行的操作越多,性能上的差异就越明显.

.net相关问答推荐

升级到.NET8后,SignalR(在坞站容器上)网关损坏

有没有更好的方法使用 Pusher Channels 的批事件发布消息?

在本地运行 Azure 函数会在 .NET7 升级后出现无运行时错误

正则表达式在空格上拆分,除非在引号中

为什么这个多态 C# 代码会打印它的功能?

设置日志(log)文件名以在 Log4j 中包含当前日期

从 switch 块中跳出 foreach 循环

将 DataRowCollection 转换为 IEnumerable

.NET 中是否有一种简单的方法来获得数字的st、nd、rd和th结尾?

使用 Windows 服务和 C# 检测 USB 驱动器插入和移除

为什么字典比列表快得多?

Convert.ToBoolean 和 Boolean.Parse 不接受 0 和 1

如何将 System.Type 转换为其可为空的版本?

Moq - 不可覆盖的成员不能用于设置/验证表达式

静态方法继承的正确替代方法是什么?

如何访问 Session 变量并在 javascript 中设置它们?

了解 C# 中的协变和逆变接口

如何比较泛型类型的值?

MVC4 HTTP 错误 403.14 - 禁止

如何使用 NPOI 读取文件