当我们使用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相关问答推荐

使用 SSH.NET 查找具有特定文件名的最新 SFTP 文件

如何知道变量是否只是指向另一个对象的pointer或者它是否可以独立存在

在 C# 中将字符串转换为 colored颜色

是否有任何 x 次的 for 循环的更短/更简单的版本?

LINQ:确定两个序列是否包含完全相同的元素

为什么 .NET 中没有可序列化 XML 的字典?

如何在 WPF 应用程序中使用 App.config 文件?

如何使用c#从excel文件中读取数据

如何将 UI Dispatcher 传递给 ViewModel

如何对无法加载的 VSTO 插件进行故障排除?

从 .NET 中的字符串末尾修剪字符串 - 为什么会丢失?

关闭 Visual Studio 中所有选项卡但当前选项卡的键盘快捷键?

互锁且易变

EF Core 添加迁移构建失败

IronPython 与 Python .NET

C# 应用程序中的全局键盘捕获

我可以将构造函数参数传递给 Unity 的 Resolve() 方法吗?

C# ListView 列宽自动

在类型 c# 上切换大小写

C#/.NET 中仅命名空间的类可见性?