考虑一个返回结构的方法,如下所示:
Public Function DoWork() As MyStructure
Return New MyStructure(1.5, 1.7, 1.1, 55.9)
End Function
Run Code Online (Sandbox Code Playgroud)
在这种情况下,.NET是否创建并初始化一次或两次MyStructure值?
编辑:我的预感是,调用DoWork必须涉及.NET从一开始就推送堆栈上的返回值.否则,怎么会Return回到调用代码?所以这是我正在谈论的第一次初始化.
第二次初始化将在Return语句中,其中参数1.5,1.7,1.1,55.9初始化一个新MyStructure值.上Return,.NET会再覆盖上新的返回值堆栈现有的值.
问题是,我对.NET的工作原理知之甚少.我对Stacks如何工作的概念是基于在DOS下,在80年代早期尝试在Pascal中编码的模糊回忆.我不知道.NET/Windows如何做这些事情!
只需看看生成的机器代码,看看会发生什么.首先需要更改选项以确保启用优化程序,工具>选项>调试>常规>取消选中"抑制JIT优化"复选框.切换到发布版本.在DoWork调用上设置断点,当它命中时使用Debug> Windows> Disassembly来查看生成的机器代码.
关于你所看到的,我会面对一点.你的直觉是正确的,只返回简单的标量值是有效的,它们适合CPU寄存器.不是这种结构,调用方法必须在其堆栈帧上保留空间,以便被调用者可以在那里存储结构.它传递指向该保留空间的指针.换句话说,如果你把这个方法声明为没有真正的区别Public Sub DoWork(ByRef retval As MyStructure).
只有通过内联函数,才能优化此代码的其他方式.x86抖动不会这样做,它对返回结构的方法很挑剔.事实上,x64抖动实际上是内联方法,但随后它完成了一个绝对可怕的工作.它仍然保留返回值的空间,然后生成许多不必要的初始化和值移动代码.非常残忍.这个抖动被重写为VS2015(项目名称RyuJIT),我还没有安装它,看它是否做得更好.
绘制的基本结论:此代码未优化.传递ByVal时,结构运行良好.不要让这个痉挛你的风格,我们在这里谈论纳秒.
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |