Debugging, Profiling and Performance

47.1 Compiler Flags

-O, -O3, -Os, -Oz Release (disable asserts/contracts) -mcpu=native (limited) -mcpu=native, -mattr=+avx2

-preview=dip1000, -preview=in, -preview=nosharedaccess GC allocation report -profile, -profile=gc -fprofile-instr-generate (PGO) Template bloat info

47.2 Debugging

Build with -g (LDC/GDC give the best debugger experience), then use gdb ./app / lldb ./app (D demangling is built into GDB). VS Code with code-d + CodeLLDB/C++ debugger. Visual D on Windows.

writeln/debug writeln, assert, stack traces on exceptions (with -g), core.runtime trace handlers, --DRT-trapExceptions=0 (break where the exception is thrown).

dustmite reduces failing test cases (including compiler bugs).

47.3 Profiling

Tools: perf, Valgrind, Intel VTune, Tracy (bindbc-tracy), hotspot. Benchmark with std.datetime.stopwatch.benchmark.

dmd -profile app.d && ./app          # trace.log + trace.def (function timings)
dmd -profile=gc app.d && ./app       # profilegc.log (allocations by site)
./app --DRT-gcopt=profile:1          # GC pause statistics
perf record ./app && perf report     # Linux perf (build with LDC -g -O)
valgrind --tool=callgrind ./app

47.4 Performance Tips

Use LDC with -O3 -release -boundscheck=off -mcpu=native -flto=thin for maximum speed (keep bounds checks for safety-critical code).

Avoid hidden GC allocations in hot paths (check with -vgc, use @nogc): array literals, closures, ~ concatenation, .array, string formatting.

Preallocate (reserve, appender, uninitializedArray). Reuse buffers (byLine vs byLineCopy).

Prefer ranges and templates (static dispatch) over classes and virtual calls in hot loops. Use final classes and methods.

Avoid autodecoding overhead with .byCodeUnit / .representation for ASCII/byte processing.

Use std.parallelism for CPU-bound work. Tune or disable the GC around critical sections (GC.disable).

Struct of arrays and cache-friendly layouts. Use scope to enable stack allocation.