Debugging and profiling tools
Read time 5 minutesLast updated 13 days ago
The following sections describe how to debug and profile your Burst-compiled code in the Editor and in Player builds.
Debugging Burst-compiled code in the Editor
To debug Burst-compiled code in the Editor, you can either use a managed debugger or a native debugger. This section explains both options.
Attach a managed debugger
You can attach a managed debugger such as Visual Studio or JetBrains Rider. This is the same type of debugger you can use to debug regular managed C# code in your Unity project.
When you place a breakpoint inside Burst-compiled code, and you have a managed debugger attached, Unity disables Burst automatically for that code path. This allows you to use a managed debugger to debug the managed version of your code. When you remove all breakpoints from that code path, Unity re-enables Burst for that code path.
Attach a native debugger
You can attach a native debugger such as Visual Studio or Xcode. Before doing so, you need to disable Burst optimizations. You can do this in the following ways:
-
Use the Native Debug Mode Compilation setting in the Editor Burst menu (Jobs > Burst > Native Debug Mode Compilation). Important: This setting disables optimizations across all jobs, which impacts the performance of Burst code. If you want to disable optimizations only for a specific job, use the other option in this list.
-
Add theflag to your job, which disables optimizations and enables debugging on that specific job:
Debug = true[BurstCompile(Debug = true)]public struct MyJob : IJob{ // ...}
To attach a native debugger to the Unity Editor process, refer to native debugging.
Debugging Burst-compiled code in a Player build
Because of how Unity builds the code for a Player, you need to tell the debugging tool where to find the symbols. To do this, point the tool to the folder that contains the files, which is usually in the folder.
lib_burst_generatedPluginsTo debug Burst-compiled code in a Player build, you need to attach a native debugger (such as Visual Studio or Xcode) to the player process. Before doing so, you need to:
-
Enable symbol generation. You can do this in either of two ways:
-
Enable theoption before you build the Player, orDevelopment Build
?
-
Enable the Force Debug Information option in Burst AOT Player Settings
-
-
Disable Burst optimizations. You can do this in either of two ways:
-
Disable the Enable Optimizations option in Burst AOT Player Settings. Important: This setting disables optimizations across all jobs, which impacts the performance of Burst code. If you want to disable optimizations only for a specific job, use the other option in this list.
-
Add theflag to your job, which disables optimizations and enables debugging on that specific job:
Debug = true[BurstCompile(Debug = true)]public struct MyJob : IJob{ // ...}
-
To attach a native debugger to the Player process, refer to native debugging.
Native debugging
Follow the previous instructions to set up native debugging correctly for the Editor or a Player build. Then, attach a native debugger such as Visual Studio or Xcode.
Native debugging limitations
- Native debuggers can't discover lambda captures on , so you can't inspect variables originating from these.
Entity.ForEach - Structs that use and have overlapping fields are represented by a struct that hides one of the overlaps.
[StructLayout(LayoutKind=Explicit)]
Nested types are namespaced in C/C++ style as shown in the following example:
namespace Pillow{ public struct Spot { public struct SubSpot { public int a; public int b; } public int a; public int b; public SubSpot sub; }
You would refer to as in this case, for example, if you were trying to cast a pointer in a debugger watch window).
SubSpotPillow::Spot::SubSpotCode-based breakpoints
Burst supports code-based breakpoints through the method. This method generates a debug trap in your code. You must attach a debugger to your code so that it can intercept the break. Breakpoints trigger whether you've attached a debugger or not.
System.Diagnostics.Debugger.BreakBurst adds information to track local variables, function parameters, and breakpoints. If your debugger supports conditional breakpoints, use these over adding breakpoints in your code, because they only fire when you've attached a debugger.
Profiling Burst-compiled code
You can use profiling tools (such as Instruments or Superluminal) to profile Burst-compiled code in a Player build. Because of how Unity builds the code for a Player, you need to tell the profiling tool where to find the symbols. To do this, point the tool to the folder that contains the files, which is usually in the folder.
lib_burst_generatedPluginsUnity Profiler markers
To improve the data you get from Unity Profiler (either for Burst-compiled code running in the Editor or in an attached Player), you can create Unity Profiler markers from Burst code by calling :
new ProfilerMarker("MarkerName")[BurstCompile]private static class ProfilerMarkerWrapper{ private static readonly ProfilerMarker StaticMarker = new ProfilerMarker("TestStaticBurst"); [BurstCompile(CompileSynchronously = true)] public static int CreateAndUseProfilerMarker(int start) { using (StaticMarker.Auto()) { var p = new ProfilerMarker("TestBurst"); p.Begin(); var result = 0; for (var i = start; i < start + 100000; i++) { result += i; } p.End(); return result; } }}