SSt*_*eve 2 c# clr optimization cil
我做了很长时间的程序员,最近找到了一份编写 C# 的工作。我很想知道 Visual Studio 是否优化了对简单内存的属性调用,而不是执行函数调用和返回。所以我写了一个程序,它有两个版本的 3D 点类和一个计算量级的方法:一个版本直接访问字段,一个版本使用属性。我用 100,000,000 点跑了两个,他们花了相同的时间。但是当我使用ildasm查看生成的代码时,使用属性的版本似乎是使用函数调用来访问属性值的。(这是一个发布版本,所以代码优化是打开的。)
我的问题:
对 get_X 的函数调用是否在运行时针对内存移动进行了优化?(看起来是这样,因为执行直接字段引用所需的时间相同。)
有没有办法使用ildasm或其他工具来查看运行时发生了哪些优化?
我尝试在没有调试器的情况下运行该进程,然后附加到该进程,但 VS2017 显示“没有可用的反汇编”。
直接调用私有字段的版本:
.method public hidebysig instance float64
Abs() cil managed
{
// Code size 47 (0x2f)
.maxstack 8
//000052: return Math.Sqrt(_x * _x + _y * _y + _z * _z);
IL_0000: ldarg.0
IL_0001: ldfld float64 CPUTests.Point3d::_x
IL_0006: ldarg.0
IL_0007: ldfld float64 CPUTests.Point3d::_x
IL_000c: mul
IL_000d: ldarg.0
IL_000e: ldfld float64 CPUTests.Point3d::_y
IL_0013: ldarg.0
IL_0014: ldfld float64 CPUTests.Point3d::_y
IL_0019: mul
IL_001a: add
IL_001b: ldarg.0
IL_001c: ldfld float64 CPUTests.Point3d::_z
IL_0021: ldarg.0
IL_0022: ldfld float64 CPUTests.Point3d::_z
IL_0027: mul
IL_0028: add
IL_0029: call float64 [mscorlib]System.Math::Sqrt(float64)
IL_002e: ret
} // end of method Point3d::Abs
Run Code Online (Sandbox Code Playgroud)
调用属性的版本,后跟get_X方法:
.method public hidebysig instance float64
Abs() cil managed
{
// Code size 47 (0x2f)
.maxstack 8
//000052: return Math.Sqrt(X * X + Y * Y + Z * Z);
IL_0000: ldarg.0
IL_0001: call instance float64 CPUTests.Point3dProperties::get_X()
IL_0006: ldarg.0
IL_0007: call instance float64 CPUTests.Point3dProperties::get_X()
IL_000c: mul
IL_000d: ldarg.0
IL_000e: call instance float64 CPUTests.Point3dProperties::get_Y()
IL_0013: ldarg.0
IL_0014: call instance float64 CPUTests.Point3dProperties::get_Y()
IL_0019: mul
IL_001a: add
IL_001b: ldarg.0
IL_001c: call instance float64 CPUTests.Point3dProperties::get_Z()
IL_0021: ldarg.0
IL_0022: call instance float64 CPUTests.Point3dProperties::get_Z()
IL_0027: mul
IL_0028: add
IL_0029: call float64 [mscorlib]System.Math::Sqrt(float64)
IL_002e: ret
} // end of method Point3dProperties::Abs
.method public hidebysig specialname instance float64
get_X() cil managed
{
// Code size 7 (0x7)
.maxstack 8
//000016: get { return _x; }
IL_0000: ldarg.0
IL_0001: ldfld float64 CPUTests.Point3dProperties::_x
IL_0006: ret
} // end of method Point3dProperties::get_X
Run Code Online (Sandbox Code Playgroud)
在调试时使用反汇编视图可能会显示属性 getter 和 setter 确实是内联的。您可以在 Visual Studio 中使用 CTRL-ALT-D 访问它。
如果您想发现抖动优化,可以使用MethodImplOptions禁用它们。
public struct foo
{
private int _bar;
public int bar
{
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
get { return _bar; }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
set { _bar = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
将在调试时向您展示:
而如果你不放属性,你甚至不能打断点,因为所有的getter都被内联了。
| 归档时间: |
|
| 查看次数: |
193 次 |
| 最近记录: |