Debugging optimized code

Report
Debugging
Production
SharePoint
Applications
Wouter van Vugt
Agenda
• How .NET and the CLR work
• Optimizing code and the effect on debuggers
• Debugging third party code
HOW .NET AND THE CLR WORK
.NET Applications
• Written in any language
• Executed in a runtime called CLR
– Shield code from hardware specifics
• Java: One language, multi OS
• .NET: Many languages, one OS (and Mono)
– Allows various types of preprocessing of code
OS
CLR
App
Common Language Runtime
Operation
• Memory management
• Thread synchronization
• Error handling
• Type Safety
Security
Execution
• Code Access Security
• Data Execution
Prevention (OS)
• Address Space Layout
Randomization (OS)
• Intermediate Language
Type Safety
• Type Safety
– A pointer of a specific type can never point to an
object which is not of that type!
Car c = new Person()
‘Pointer type’
Pointer
Object type
– Checked at compile AND runtime!
– Knowing the actual type enables
• Reading its data  Quite useful in debugging 
• Calling its functions
Demo
TRY AND CIRCUMVENT TYPE
SAFETY
Creating .NET Applications
C#, C++,
VB.NET, F#....
(40+)
Compile
Module
PDB
Link
Assembly
PDB
Executing code
• Assemblies contain mostly IL code
– IL is the ‘Machine code’ for .NET
– Compiled to native instructions at runtime
through the JIT Compiler
– Enough information remains to decompile back to
source!
Language richness compared
Machine
Code
C#
IL
Executing code with JIT Compilation
Console.WriteLine("Hi");
Console.WriteLine("There");
Console metadata
static void WriteLine()
JIT Compiler Address
static void WriteLine(string)
JIT Native
Compiler
Address
Address
Native CPU
Instructions
JIT Compiler
-Lookup IL for method
-Compile IL to native
-Modify metadata to
point to compiled code
-Jump to compiled code
Executing code with JIT Compilation
Console.WriteLine("Hi");
Console.WriteLine("There");
Console metadata
static void WriteLine()
JIT Compiler Address
static void WriteLine(string)
Native Address
Native CPU
Instructions
JIT Compiler
-Lookup IL for method
-Compile IL to native
-Modify metadata to
point to compiled code
-Jump to compiled code
Code optimization
• Compile-time
– Constant value folding
– Remove Branch to next
instruction and NOP
instructions used to
break on control flow, {,
}, EndIf etc
– Overflow checking
–…
• During JIT
–
–
–
–
–
Eliminate local variables
Range check elimination
Method inlining
Tail call optimization
Common subexpression
elimination
– Dead code elimination
– Loop unrolling
–…
Running non optimized code
• Breakpoints
• Edit and continue
C# Compiler – Variable Generation
C# Compiler – Variable Generation
Debug
Release
C# Compiler – Inserting NOP
C# Compiler – Inserting NOP
Debug
Release
C# Compiler – Branching
C# Compiler – Branching
Debug
Release
Demo
COMPILE TIME OPTIMIZATIONS
Just In Time Compilation
• Transformation of MSIL to native x86 / x64 /
ARM etc
• Can optimize code
– Mathematically ensured correctness
• Takes a small performance hit during startup
Compiler switch
C# IL Code Quality
JIT Native Code Quality
/optimize- /debug-
Unoptimized
Optimized
/optimize- /debug+
Unoptimized
Unoptimized
/optimize+ /debug+
Optimized
Optimized
NGEN.exe
• JIT Compilation incurs a runtime cost
• NGEN pre-compiles MSIL assemblies to
machine code
• Runs as a service in the background
• Also used by the “.NET Runtime Optimization
Service”
JIT - Local variable elimination
User user = GetUser(3);
PrintUser(user);
Before
PrintUser(GetUser(3));
After
JIT – Range check elimination
static
static
static
{
for
int[] _array = new int[10];
volatile int _i;
void Main(string[] args)
Before
(int i = 0; i < _array.Length; ++i)
_i += _array[i];
}
static int[] _array = new int[10];
static volatile int _i;
static void Main(string[] args)
{
int[] localRef = _array;
for (int i = 0; i < localRef.Length; ++i)
_i += localRef[i];
}
After
JIT – Method Inlining
public class Program {
public static int And(int first, int second) {
return first & second;
}
static void Main(string[] args) {
int i = And(5, 4);
}
}
public class Program {
static void Main(string[] args) {
int i = 5 & 4;
}
}
Before
After
JIT – Tail Call Optimization
static void Main(string[] args)
{
TestTailCallOptimization();
}
public static void TestTailCallOptimization()
{
string s = "Test";
TailCall1(s);
}
static void TailCall1(string s)
{
Console.WriteLine(s);
TailCall2(s);
}
static void TailCall2(string s)
{
Console.WriteLine(s + s);
}
Loading non-precompiled assemblies
• Native NGEN images are hard to debug
– Remove the NGEN image
C:\> NGEN uninstall MyAssembly
– Or, prevent NGEN image from loading
C:\> SET COMPLUS_ZAPDISABLE=1
Preventing JIT optimization
• Creating debug builds
– JIT prevented through compile time attributes
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.Default)]
• INI file MyAssembly.ini
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
• In Visual Studio, on module load after attach
Demo
DEBUGGING OPTIMIZED CODE
Debugging code
• PDB files are as essential as code!
• Breakpoints can do way more than break
• Tracing is cheaper than debugging
• IntelliTrace can run in production
PDB Files
• Contain vital debugging information
• No PDB? Severely limited debugging experience!
• Minimal investment: Symbol server
• Managed PDB files contain
– Source file names / line numbers
– Local variable names
– Alternate streams  Used by TFS
Symbol Servers
• Central repository for storing debug symbols
• File system based technology
• Integrated into Team Foundation and Visual
Studio
Locating debug symbols
MyAssembly.dll
GUID
MyAssembly.pdb
Equal
• PDB files are located
– Same directory as module
– Hardcoded path in module
– Symbol server cache
– Symbol server
GUID
Dumpbin.exe
• Use to peek inside PE files
Prevent loading all PDBs
Visual Studio Source Server support
• Allows Visual Studio to download relevant
source files automatically from a repository.
Configuring Symbol Locations
PDB alternate streams
• Used by TFS to store server path to sources
Demo
SYMBOL SERVERS, SOURCE
SERVERS AND SOURCE INDEXING
Working with break points
Setting breakpoints on automatic
properties
• Use ‘Break at function’ and enter get_name
Setting breakpoints on automatic
properties
• Inspect callstack / locals window
Debugging third party code
• Red Gate .NET Reflector PRO
– Decompile assemblies into source code
– Generate PDB file from assembly + source
– Enables debugging third party code
Enabling remote debugging
• Run Remote Debugging x86 or x64
• Give permissions
• Connect
Demo
DEBUGGING SHAREPOINT

similar documents