C# - 可变范围和处理如何影响处理效率?

时间:2016-04-29 09:13:01

标签: c# performance scope cpu-usage dispose

前几天我和同事讨论过这个假设的情况。考虑这个伪代码:

public void Main()
{   
    MyDto dto = Repository.GetDto();

    foreach(var row in dto.Rows)
    {
        ProcessStrings(row);
    }
}

public void ProcessStrings(DataRow row)
{
    string string1 = GetStringFromDataRow(row, 1);
    string string2 = GetStringFromDataRow(row, 2);

    // do something with the strings
}

然后这个功能相同的替代方案:

public void Main()
{
    string1 = null;
    string2 = null,
    MyDto dto = Repository.GetDto();

    foreach(var row in dto.Rows)
    {
        ProcessStrings(row, string1, string2)
    }
}

public void ProcessStrings(DataRow row, string string1, string string2)
{
    string1 = GetStringFromDataRow(row, 1);
    string2 = GetStringFromDataRow(row, 2);

    // do something with the strings
}

运行编译代码时,这些处理方式有何不同?我们是否正确地认为第二个版本的效率稍微高一些,因为字符串变量将占用更少的内存并且只被处置一次,而在第一个版本中,它们在循环的每次传递中都被处理掉了?

如果第二个版本中的字符串是通过refout参数传递的,会不会有任何区别?

2 个答案:

答案 0 :(得分:2)

在两种选择中,GetStringFromDataRow每次都会创建新的字符串。是否将引用存储在本地变量或参数变量中的字符串中(在本例中与本地变量基本上没有太大差别)并不重要。想象一下,你甚至没有将GetStringFromDataRow的结果分配给任何变量 - 仍然创建字符串的实例并将其存储在内存中的某处直到收集垃圾。如果你通过引用传递你的字符串 - 它不会产生太大的影响。您将能够重用内存位置以将引用存储到已创建的字符串(您可以将其视为字符串实例的内存地址),但不能将其视为字符串内容的内存位置。

答案 1 :(得分:2)

当你处理"稍微提高效率"优化程度,你可能无法看到整体情况,最终导致效率降低......#/ p>

这里的答案有同样的风险,但有了这个警告,让我们来看看这个假设:

  

将字符串存储到变量中会创建字符串

的新实例

不,一点也不。字符串是一个对象,您在变量中存储的是对该对象的引用。在32位系统上,此引用的大小为4个字节,在64位上为8个。仅此而已。移动4/8字节是您不会真正注意到的开销。

因此,两个例子都没有,因为我们所掌握的关于调用方法的元素的信息非常少,所以创建的字符串比其他字符串更多或更少,所以在这个数字上它们是等价的。

那有什么不同?

在一个示例中,您将两个字符串引用存储到局部变量中。这很可能是cpu寄存器。可能是堆栈上的内存。很难说,取决于其余的代码。有关系吗?极不可能。

在另一个示例中,您传递了两个参数null,然后在本地重用这些参数。这些参数可以作为cpu寄存器或堆栈存储器传递。与另一个相同。这有关系吗?完全没有。

所以最有可能完全没有区别。

请注意一件事,您提及"处置"。该术语保留用于实现IDisposable的对象的使用,然后通过在这些对象上调用IDisposable.Dispose来处置这些术语。字符串不是这样的对象,这与这个问题无关。

相反,如果处置你的意思是"垃圾收集",那么因为我已经确定,由于你所询问的差异,这两个例子都没有比其他例子创造更多或更少的对象,这是也无关紧要。

然而,这并不重要。您或我或您的同事认为将会产生影响并不重要。知道是完全不同的,这导致我......

我可以给出关于优化的真实提示:

  1. 测量
  2. 测量
  3. 测量
  4. 了解
  5. 验证您是否正确理解
  6. 如果可能,请更改
  7. 您测量,使用分析器查找代码中的真正瓶颈和实时消费者,然后了解这些瓶颈的原因,然后确保您的理解是正确的,然后您可以看看是否可以更改它。

    在你的代码中,我冒昧地猜测,如果你要描述你的程序,你会发现这两个例子对运行时间没有任何影响。如果他们有效,它将在纳秒级。最有可能的是,查看分析器结果的行为将给你一个或多个"呵呵,那个奇怪的"关于你的程序的实现,你会发现比这里的变量更大的瓶颈。