返回字符串时的编译器优化

时间:2013-06-11 13:03:07

标签: c# compiler-construction compiler-optimization

如果我有

private string Foo(string decrypted)
{
    return decrypted.Substring(blah);
}

private string Foo(string decrypted)
{
    string s = decrypted.Substring(blah);
    return s;
}

这是一样的吗?编译器是否能够删除s

怎么样

private string Foo(string decrypted)
{
    string s = decrypted.Substring(blah);
    string t = s;
    return t;
}

感谢。

2 个答案:

答案 0 :(得分:4)

我很好奇,所以我试了一下(使用LINQPad 4进行优化)。这就是我得到的:

private string Foo(string decrypted)
{
    return decrypted.Substring(0);
}
Foo:
IL_0000:  ldarg.1     
IL_0001:  ldc.i4.0    
IL_0002:  callvirt    System.String.Substring
IL_0007:  ret        

private string Foo(string decrypted)
{
    string s = decrypted.Substring(0);
    return s;
}
Foo:
IL_0000:  ldarg.1     
IL_0001:  ldc.i4.0    
IL_0002:  callvirt    System.String.Substring
IL_0007:  stloc.0     // s
IL_0008:  ldloc.0     // s
IL_0009:  ret     

private string Foo(string decrypted)
{
    string s = decrypted.Substring(0);
    string t = s;
    return t;
}
Foo:
IL_0000:  ldarg.1     
IL_0001:  ldc.i4.0    
IL_0002:  callvirt    System.String.Substring
IL_0007:  stloc.0     // s
IL_0008:  ldloc.0     // s
IL_0009:  stloc.1     // t
IL_000A:  ldloc.1     // t
IL_000B:  ret    

看起来编译器没有优化st,但是,我怀疑JIT解释器会。{/ p>

答案 1 :(得分:1)

在我看来问题基本上是“C#编译器是否支持named return value optimization(NRVO)?”

我认为这是一个合理的问题,但与delnan points out一样,它并不是特别相关,因为C#中的字符串是引用类型。如果您是C ++程序员,您可以将引用类型视为与指针基本相同。因此,尽管您按值返回字符串,但实际上只是按值返回引用,而不是对象本身。就像你按值返回指针地址一样。不需要制作整个字符串对象的副本,因此优化会使您获得很少的收益。您需要NRVO的唯一原因是避免遭受大型昂贵副本的性能损失,但复制指针/引用并不昂贵。

但是,如果您给出了使用值类型而不是引用类型(例如,大型结构)的不同示例,那么通过实现NRVO可能会获得显着的性能提升。不幸的是,即使在这种情况下,我也不相信C#编译器会这样做。我想JITer可能会;我不能肯定地说。 (如果现在还没有完成,可以在将来的版本中添加它。虽然在C#代码中很少发现这种大型结构,但是这不太可能是性能团队目标列表的顶部。)

有关详细信息,建议您阅读Jon Skeet关于C#中References and Values的文章。