如何验证 C# 中的函数是否已缓存?
我在 C# 中创建了以下函数:
float GetPI()
{
return 22.0f/7.0f;
}
void Calculate()
{
float f1 = GetPI()*4;
float f2 = GetPI()*5;
}
如果我创建发布版本,我将如何验证 JIT 编译器是否会缓存 22/7 计算,或者是否会在每次调用函数 GetPI 时进行计算?
PS:我没有 Visual C# studio 专业版
编辑:将 22/7 更改为 22.0f/7.0f 以使示例功能更准确
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不确定你所说的缓存是什么意思。除非编译器不执行任何常量折叠(在本例中它将执行)或者运行时不会内联您的函数(在本例中可能会执行),否则它不会自动为您执行任何“缓存”。
表达式
22f/7f
是一个常量表达式,可以在编译时求值(又名 不断折叠)。因此在编译后的程序集中,它将显示为:如果有机会,编译器将始终进行这种优化。除非有一个编译器选项可以禁用它(我不确定是否有)。为了验证这种情况是否发生,您可以使用 Reflector(正如其他人指出的那样)来查看编译后的程序集。您应该看到,无论是调试或发布版本还是使用快速版本,它确实会执行此操作(除非显式禁用此优化)。
如果函数足够简单,运行时可能会内联您的函数调用。因此,它不会调用此函数,而是插入结果来代替函数调用。由于这只是一个返回一些数字的函数,因此它可能会进行此优化。我不知道是否有一种方法可以在不通过调试器实际查看 JIT 编译的代码的情况下查看是否发生这种情况。
如果您的意思是像 memoization 中那样进行缓存,那么这不会自动完成,您将拥有自己做这件事。
如果您想要绝对保证编译器将“缓存”(如不重新计算商)该值,您应该将您的值声明为常量(或使用现有的且更准确的
System.Math.PI
常量)。没有什么是在运行时确定的,一切在编译时都是已知的。每次您使用此值时,它都会被“内联”,因此您不必担心这一点。I'm not sure what you mean by being cached. Unless the compiler doesn't do any constant folding (which it will in this case) or the runtime doesn't inline your function (which it probably would in this case), it will not do any "caching" automatically for you.
The expression
22f/7f
is a constant expression and can be evaluated at compile time (aka, constant folding). So in the compiled assembly, it will appear as:The compiler will always make this kind of optimization if given the opportunity. Unless there's a compiler option to disable this (which I'm not sure there is). To verify this happens, you could use Reflector (as the others have pointed out) to see the compiled assembly. You should see that it does indeed do this whether it is Debug or Release builds or using the express versions (unless this optimization is explicitly disabled).
If the function is simple enough, the runtime might inline your function call. So rather than calling this function, it will insert the result in place of the function call. Seeing as this is just a function to just return some number, it will probably will do this optimization. I don't know if there even is a way to see if this happens without actually seeing the JIT compiled code through a debugger.
If you mean caching as in memoization, then no this will not be done automatically and you'll have to do this yourself.
If you want an absolute guarantee that the compiler will "cache" (as in not recalculate the quotient) the value, you should declare your value as a constant (or use the existing and more accurate
System.Math.PI
constant). Nothing is being determined at runtime, everything is known at compile time. And every time you use this value, it will be "inlined" so you won't have to worry about that.下载并安装 .NET Reflector(最初由 Lutz Roeder 编写,现在由 Red Gate 维护)。如果您不想付费,您可能必须寻找旧版本。
当您在 Reflector 中打开代码时,您可以看到编译器所做的更改。
这不会向您显示 JIT 优化,您需要在调试器中单步执行机器代码,但我很确定这种情况将由 C# 编译器进行评估。
Download and install .NET Reflector (originally written by Lutz Roeder, and now maintained by Red Gate). You may have to look for an older version if you don't want to pay.
When you open your code in Reflector, you can see what changes the compiler made.
This wouldn't show you JIT optimizations, you need to step through the machine code in a debugger for that, but I'm pretty sure this case will be evaluated by the C# compiler.
有很多方法。一种方便的方法是使用 .NET Reflector。
在 Reflector 中打开程序集,选择 C#,在树视图中找到该方法,然后选择“工具/反汇编”。反汇编程序将显示如下内容:
There are many ways. One convenient is using .NET Reflector.
Open up your assembly in Reflector, select C#, find the method in the treeview, select Tools/Disassemble. The disassembler will show something like the following: