0

I have created the following functions in C#:

float GetPI()
{
  return 22.0f/7.0f;
}

void Calculate()
{
  float f1 = GetPI()*4;
  float f2 = GetPI()*5;
}

If I create a release build, how will I be able to verify whether the JIT compiler will cache the 22/7 calculation, or whether it will be calculated each time the function GetPI is called?

PS : I do not have visual C# studio professional edition

EDIT : changed 22/7 to 22.0f/7.0f to make the example function more accurate

5
  • 2
    Why not just use Math.PI: msdn.microsoft.com/en-us/library/system.math.pi.aspx Commented Mar 20, 2011 at 23:27
  • Tip: you should have return 22.0f/7.0f; Commented Mar 20, 2011 at 23:27
  • 1
    3 is an awfully inaccurate approximation for pi. And not using the already-invented wheels is even worse. More generally speaking, unless you have a very good reason to do otherwise (it's highly unlikely you have!), you should just trust the fairies that make your code run. Their creators know what they're doing. Commented Mar 20, 2011 at 23:27
  • 1
    thanks for your replies. i am actually wanting to know the role played by JIT compiler. Please consider this getPI as any general function which is constant Commented Mar 20, 2011 at 23:33
  • 3
    @delnan & @Kent: I think you guys might be taking his example too literally. Commented Mar 20, 2011 at 23:35

3 Answers 3

4

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:

float GetPI()
{
  return 3.142857f; // however many digits of precision
}

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.

const float PI = 22f / 7f; // will be stored as 3.142857f

// or another way, if you need PI to be a float but want a more accurate value
const float PI = (float)Math.PI; // will store as much precision possible
// note that this only works because Math.PI is declared as a constant
Sign up to request clarification or add additional context in comments.

Comments

1

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.

3 Comments

will not debugger generate different code since it will be debug build?
@quantcoder: That depends on what part of the code we're speaking. I don't believe that many compilers make a distinction between release and debug builds when it comes to changing a calculation of constants to the constant result.
@quantcoder: You will have to load a release build into the debugger, and you'll also have to use "attach to process", because if the process is started with the debugger attached, that will also disable JIT optimization.
1

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:

public float GetPI()
{
    return 3f;
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.