I am trying to investigate a performance problem where an application runs slowly when run in 64bit on one of our servers, while it runs fast in 32 bit on that same machine or 64 bit anywhere else.
I have seen that this could be related to the JIT compiler being used. Is there a way I can tell which JIT compiler is being used to run my application? I'd like to see if it's different on the server than on the other computers where the 64 bit version works fine.
JIT Version
You can follow Hans' steps to verify that RyuJIT is loaded into your application. [2]
use the debugger to ensure you have the new version. First have a look-see at the runtime directory with Explorer, navigate to C:\Windows\Microsoft.NET\Framework64\v4.0.30319. You'll find the the two jitters there, clrjit.dll is new jitter based on the Ryujit project and compatjit.dll is the legacy x64 jitter.
Project > Properties > Debug > tick the "Enable native code debugging option". Use the Build tab and ensure you've removed the jitter forcing, the "Prefer 32-bit" option must be unticked, "Platform target" must be set to AnyCPU. And use the Application tab to pick the framework target.
Use Debug > Step Into to start debugging. Debug > Windows > Modules displays the list of loaded modules. Find the jitter DLLs back in that list, click the "Name" column header to sort by name. If you see compatjit.dll back then you are using the legacy jitter. Do note that you'll always see clrjit.dll, they both get loaded when the legacy jitter is used.
[2] https://stackoverflow.com/a/31534544/102351
JIT Architecture
You can determine the architecture of the JIT used by checking whether the running application is a 64-bit process or not.
Environment.Is64BitProcess
https://msdn.microsoft.com/en-us/library/system.environment.is64bitprocess.aspx
This property is implemented as a direct true/false return within the 64-bit and 32-bit versions of mscorlib, respectively. [1]
[1] https://stackoverflow.com/a/1913908
Use the JIT performance counters (https://msdn.microsoft.com/en-us/library/w8f5kw2e(v=vs.110).aspx#jit) to monitor when code is being jitted.
You can use ngen (https://msdn.microsoft.com/en-us/library/6t9t5wcf(v=vs.110).aspx) to improve application start-up time by removing the need to JIT code - ngen pre-compiles assemblies into native images.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Disassembly view of C# 64-bit Release code is 75% longer than 32-bit Debug code?
I have an extremely simple C# Console Application, hat does some sorting on a big number of elements (only a few lines of code with array operations).
When I start the release code from Visual Studio IDE with F5 or Ctrl-F5 the program is about 3x slower than when started directly from Win-Explorer.
41.140 seconds when launched from VS 2010 IDE
13.950 seconds when launched by double-clicking myprogram.exe
Why???
First some details...
Be aware that there are 2 main "optimization" stages in .NET.
At the C# Compiler level...the production of different IL (Intermediate Language)...optimized or non-optimized....controlled by whether your project sets the DEBUG flag or not
At the JITer level...when the IL is translated into machine code (either through Just-in-Time compilation or via NGEN)....optimized machine code may or may not be producedNote: it is NOT the IL produced via the compiler in DEBUG or RELEASE mode that controls the JITter optimization setting...it's an independent setting.
The main optimization "wins" occur at the JIT level.
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/57db50f1-54c7-4730-a097-c4976bb3a30b/
When you are debugging a NET program through Visual Studio, normally you don't want the JITter to produce optimized machine code, because then your program source statements aren't closely in sync with the executing code when you step through it.
So that's why there is an option in Visual Studio to turn off JITter optimizations (this is comparable to turning off JITter optimizations with the AllowOptimize=0 flag)...and by default Visual Studio turns JITter optimizations off:
See this for an explanation of the Suppress option:
http://msdn.microsoft.com/en-us/library/ms241594(v=vs.85).aspx
When you run a NET application outside of Visual Studio it doesn't matter if that program was compiled as DEBUG (non-optimized IL) or RELEASE (optimized IL)....the JITter will produce optimized machine code by default.
So the behaviour to be noticed is that a NET program will run
substantially faster when started outside of Visual Studio than when
started from Visual Studio due to the different JITter optimization
setting...even when it's a RELEASE mode application....as #Knasterbax
observed. In addition, there's additional overhead to add when debugging (F5) and not just running (CTRL+F5) from Visual Studio.
If you run your application (whether RELEASE or DEBUG) from Explorer and then you "attach" to the process with Visual Studio, then your application will be using a JITter that is applying optimizations....your code will run faster...but any source code stepping will not be in sync.
If you untick the "Suppress JIT optimizations" then you can gain faster execution at the expense of a poorer debugging experience in Visual Studio.
To end, there is a way to turn off JITter Optimizations for your application code should you need/want to:
disable JITter for entire application by putting this into app.config
[.NET Framework Debugging Control] AllowOptimize=0
you can tell the JITter not to optimize specified methods by using this attribute
[MethodImpl(MethodImplOptions.NoOptimization)]
on method bodies.
F5 is start debugging, not "run", it will be doing a lot of things like loading symbols in the background, even if you're attempting to debug a release build.
Starting a program with the debugger attached will always be significantly slower than without it.
When you compile the code in debug mode, the compiler switches off some optimisations, and it adds some extra instructions, to make it possible to put breakpoints everywhere and to make it possible to single step through the code.
This will make code compiled in debug mode slower than code compiled in release mode.
In Visual Studio for a C# project, if you go to Project Properties > Build > Advanced > Debug Info you have three options: none, full, or pdb-only.
Which setting is the most appropriate for a release build?
So, what are the differences between full and pdb-only?
If I use full will there be performance ramifications? If I use pdb-only will it be harder to debug production issues?
I would build with pdb-only. You will not be able to attach a debugger to the released product, but if you get a crash dump, you can use Visual Studio or WinDBG to examine the stack traces and memory dumps at the time of the crash.
If you go with full rather than pdb-only, you'll get the same benefits, except that the executable can be attached directly to a debugger. You'll need to determine if this is reasonable given your product & customers.
Be sure to save the PDB files somewhere so that you can reference them when a crash report comes in. If you can set up a symbol server to store those debugging symbols, so much the better.
If you opt to build with none, you will have no recourse when there's a crash in the field. You won't be able to do any sort of after-the-fact examination of the crash, which could severely hamper your ability to track down the problem.
A note about performance:
Both John Robbins and Eric Lippert have written blog posts about the /debug flag, and they both indicate that this setting has zero performance impact. There is a separate /optimize flag which dictates whether the compiler should perform optimizations.
WARNING
MSDN documentation for /debug switch (In Visual Studio it is Debug Info) seems to be out-of-date! This is what it has which is incorrect
If you use /debug:full, be aware that there is some impact on the
speed and size of JIT optimized code and a small impact on code
quality with /debug:full. We recommend /debug:pdbonly or no PDB for
generating release code.
One difference between /debug:pdbonly and /debug:full is that with
/debug:full the compiler emits a DebuggableAttribute, which is used to
tell the JIT compiler that debug information is available.
Then, what is true now?
Pdb-only – Prior to .NET 2.0, it helped to investigate the crash dumps from released product (customer machines). But it didn't let attaching the debugger. This is not the case from .NET 2.0. It is exactly same as Full.
Full – This helps us to investigate crash dumps, and also allows us to attach debugger to release build. But unlike MSDN mentions, it doesn't impact the performance (since .NET 2.0). It does exactly same as Pdb-only.
If they are exactly same, why do we have these options? John Robbins (windows debugging god) found out these are there for historical reasons.
Back in .NET 1.0 there were differences, but in .NET 2.0 there isn’t.
It looks like .NET 4.0 will follow the same pattern. After
double-checking with the CLR Debugging Team, there is no difference at
all.
What controls whether the JITter does a debug build is the /optimize
switch. <…>
The bottom line is that you want to build your release builds with
/optimize+ and any of the /debug switches so you can debug with source
code.
then he goes on to prove it.
Now the optimization is part of a separate switch /optimize (in visual studio it is called Optimize code).
In short, irrespective of DebugInfo setting pdb-only or full, we will have same results. The recommendation is to avoid None since it would deprive you of being able to analyze the crash dumps from released product or attaching debugger.
You'll want PDB only, but you won't want to give the PDB files to users. Having them for yourself though, alongside your binaries, gives you the ability to load crash dumps into a debugger like WinDbg and see where your program actually failed. This can be rather useful when your code is crashing on a machine you don't have access to.
Full debug adds the [Debuggable] attribute to your code. This has a huge impact on speed. For example, some loop optimizations may be disabled to make single stepping easier. In addition, it has a small effect on the JIT process, as it turns on tracking.
I'm in the process of writing a unhandled exception handler and the stack trace includes the line number when pdb-only is used, otherwise I just get the name of the Sub/Function when I choose None.
If I don't distribute the .pdb I don't get the line number in the stack trace even with the pdb-only build.
So, I'm distributing (XCOPY deploy on a LAN) the pdb along with the exe from my VB app.
Q1) Why is C# initially compiled to IL and then at runtime JIT complied and run on top of a virtual machine(?). Or is it JIT complied to native machine code?
Q2) If the second is true (JIT complied to native machine code), then where is the .NET sandbox the code runs under?
Q3) In addition, why is the code compiled to IL in the first place. Why not simply compile to native machine code all the time? There is a tool from MS from this called ngen but why is that optional?
The IL is JIT'd (JIT = Just In Time) compiled to native machine code as the process runs.
The use of a virtual machine layer allows .NET to behave in a consistent manner across platforms (e.g. an int is always 32 bits regardless of whether you're running on a 32- or 64- bit machine, this is not the case with C++).
JIT compiling allows optimisations to dynamically tailor themselves to the code as it runs (e.g. apply more aggressive optimisations to bits of code that are called frequently, or make use of hardware instructions available on the specific machine like SSE2) which you can't do with a static compiler.
A1) JIT compiles to native machine code
A2) In .net there is no such term as sandbox. There is AppDomains instead. And they runs as part of CLR (i.e. as part of executable process)
A3) NGen drawbacks from Jeffrey Richter:
NGen'd files can get out of sync.
When the CLR loads an NGen'd file, it compares a
number of characteristics about the previously compiled code and the current execution
environment. If any of the characteristics don't match, the NGen'd file cannot be
used, and the normal JIT compiler process is used instead.
Inferior Load-Time Performance (Rebasing/Binding).
Assembly files are standard Windows PE files, and, as such, each contains a preferred base address. Many Windows
developers are familiar with the issues surrounding base addresses and rebasing. When JIT compiling code, these issues aren't a concern because correct memory address references are calculated at run time.
Inferior Execution-Time Performance.
When compiling code, NGen can't make as many
assumptions about the execution environment as the JIT compiler can. This causes
NGen.exe to produce inferior code. For example, NGen won't optimize the use of
certain CPU instructions; it adds indirections for static field access because the actual
address of the static fields isn't known until run time. NGen inserts code to call class
constructors everywhere because it doesn't know the order in which the code will execute
and if a class constructor has already been called.
You can use NGEN to create native versions of your .NET assemblies. Doing this means that the JIT does not have to do this at runtime.
.NET is compiled to IL first and then to native since the JIT was designed to optimize IL code for the current CPU the code is running under.
.NET code is compiled to IL for compatability. Since you can create code using C#, VB.NET, etc then the JIT needs a common instruction set (IL) in order to compile to native code. If the JIT had to be aware of languages, then the JIT would need to be updated when a new .NET language was released.
I'm not sure about the sandbox question, my best guess is that a .NET app runs with 3 application domains. One domain contains the .NET runtimes (mscorlib, system.dll, etc), another domain contains your .NET code, and I can't recall what the other domain's for.
Check out http://my.safaribooksonline.com/9780321584090
1. C# is compiled in to CIL (or IL) because it shares a platform with the rest of the .NET languages (which is why you can write a DLL in C# and use it in VB.NET or F# without hassle). The CLR will then JIT Compile the code into Native Machine Code.
.NET can also be run on multiple platforms (Mono on *NIX and OS X). If C# compiled to native code, this wouldn't be nearly as easy.
2. There is no sandbox.
3. Covered in the answer to #1
A1) This way it's platform agnostic (Windows, Linux, Mac) and it can also use specific optimizations for your current hardware. When it gets JIT compiled it's to machine code.
A2) The whole framework (the .NET framework) is all sandbox so all calls you might make through your app will go through the .NET framework sandbox.
A3) As in answer 1, it allows the .NET binary to work in different platforms and perform specific optimizations in the client machine on the fly.
Compiled .Net code becomes IL which is an intermediate language in the exact same way as that of Javas' object code. Yes it is possible to generate native machine code using the NGen tool. NGen binds the resulting native image to the machine, so copying the ngen'd binary to a different system would not produce expected results. Compiling to intermediate code allows for runtime decisions that can be made that otherwise can't (easily) be made with a staticly-typed language like C++, it also allows the functioning of code on different hardware archetectures because the code then becomes descriptive in the sense that it also describes the intent of what should happen in a bit (eg 32 or 64)-agnostic way, as opposed to machine-specific code that only works on 32-bit systems or 64-bit systems but not both.
Also, NGen is optional because as I said it binds the binary to the system, it can be useful when you need the performance of compiled machine code with the flexibility of a dynamically typed language and you know that the binary won't be moving to a system it's not bound to.
Does anyone have any advice about extending our SVN & Cruise Control CI process to populate a Symbol Server?
We are trying to remotely debug test environments for our ASP.NET 2.0 C# website and have been running into problems getting the correct symbols to always load.
Our build process is done in release mode not debug mode so how does this affect the creation of PDB files?
Using VS2008, we have solved several issues in connecting to remote debugging since the test environments are not in the same domain. We are now getting this message when trying to watch variables:
Cannot obtain value of local or argument 'xxxxx' as it is not available at this instruction pointer, possibly because it has been optimized away
Is this because our build and subsequent deployment process is in release mode?
This error message comes because the CLR itself has optimized out the variables. The PDB's still contain all of the information about the locals in release mode, the debugger is just simply unable to access them.
It is possible though to build in release mode and generally avoid this problem. One of the factors as to whether or not the CLR will optimize in such a way that locals are not visible is the DebuggableAttribute class.
This attribute is generally emitted by the compiler and it changes the flags based on the projects mode: Release or Debug. If the attribute already exists in your project though, the compiler will not overwrite it.
If your have a web application (vs a web site) you can just add the following line to AssemblyInfo.cs and it should fix the problem
[assembly: Debuggable(DebuggingModes.DisableOptimizations)]
Note this does disable performance optimizations so you probably don't want to actually release this way but it's helpful for debugging.
Continuing from my previous question, is there a comprehensive document that lists all available differences between debug and release modes in a C# application, and particularly in a web application?
What differences are there?
"Debug" and "Release" are just names for predefined project configurations defined by Visual Studio.
To see the differences, look at the Build Tab in Project Properties in Visual Studio.
The differences in VS2005 include:
DEBUG constant defined in Debug configuration
Optimize code enabled in Release configuration
as well as other differences you can see by clicking on the "Advanced" button
But you can:
Change the build settings for Debug and Release configurations in Project Propeties / Build
Create your own custom configurations by right-clicking on the solution in Solution Explorer and selecting Configuration Manager
I think the behaviour of the DEBUG constant is fairly clear (can be referenced in the #if preprocessor directive or in the ConditionalAttribute). But I'm not aware of any comprehensive documentation on exactly what optimizations are enabled - in fact I suspect Microsoft would want to be free to enhance their optimizer without notice
I'm not aware of one concise document, but:
Debug.Write calls are stripped out in Release
In Release, your CallStack may look a bit "strange" due to optimizations, as outlined by Scott Hanselman
There isn't one document that lists the differences. In addition to some of the differences already listed, compiling in Debug mode turns off most of the JIT compiler optimizations that are performed at runtime and also emits more complete debug information in to the symbol database file (.pdb).
Another big difference is that the GC behavior is somewhat different in that the JIT compiler will insert calls to GC.KeepAlive() as appropriate/needed in order to support debugging sessions.
Debug and Release are just labelling for different solution configurations. You can add others if you want. If you wish you can add more configurations from configuration manager–
http://msdn.microsoft.com/en-us/library/kwybya3w.aspx
Major differences –
In a debug DLL several extra instructions are added to enable you to set a breakpoint on every source code line in Visual Studio. Also, the code will not be optimized, again to enable you to debug the code.
In the release version, these extra instructions are removed.
PDB file is created in only Debug mode and not in release mode.
In release mode, code is optimized by the optimizer that's built into the JIT compiler. It makes the following optimizations:
• Method inlining - A method call is replaced by the injecting the code of the method.
• CPU register allocation - Local variables and method arguments can stay stored in a CPU register without ever (or less frequently) being stored back to the stack frame
• Array index checking elimination - An important optimization when working with arrays (all .NET collection classes use an array internally). When the JIT compiler can verify that a loop never indexes an array out of bounds then it will eliminate the index check.
• Loop unrolling - Short loops (up to 4) with small bodies are eliminated by repeating the code in the loop body.
• Dead code elimination - A statement like if (false) { /.../ } gets completely eliminated.
• Code hoisting- Code inside a loop that is not affected by the loop can be moved out of the loop.
• Common sub-expression elimination. x = y + 4; z = y + 4; becomes z = x
One major performanance area if you are using any of the ASP.NET Ajax controls: debug information is removed from the JavaScript library when running in release, and I have seen major preformance improvements on complicated pages. Other web based resources may be either cached or not cached based on this setting.
Also, remember that Debug / Release in a web application is dictated by the web.config file, not your settings within Visual Studio.
<system.web>
<compilation debug="true">
More information:
Don’t run production ASP.NET Applications with debug=”true” enabled
You can also manage some part of code that you want to run only in debug or only in release with preprocessor markups:
#if DEBUG
// Some code running only in debug
#endif
or
#if NOT DEBUG
// Some code running only in release
#endif
Drawing with GDI+ is considerably slower in Debug mode.
Release version:
is considerable faster (most important), optimized
can't be debuged (step by step)
and code written in "debug" directive is not included
See What's the difference between a Debug vs Release Build?.
I got an error message when I distribute executable file to another machine indicating that the system missed MSVCP110D.dll.
The solution to this issue is stated in Stack Overflow question Visual Studio MSVCP110D.dll is missing.
IN XXXXD.dll D means that the DLL file is a debug version of the DLL file. But MS Visual C++ Redistributable packages include only the release version of DLL files.
That means if you need to distribute a program developed by Visual C++ you need to build it in Release mode. And also you need to install MS Visual C++ Redistributable (correct version) on the target machine.
So I think this a one of key difference between debug and release mode.