Debugging, Diagnostics, and Performance
Prerequisites: Exception handling
The debugger
In Visual Studio, click in the margin (or press F9) to set a breakpoint, then press F5. When execution stops:
- F10 steps over a line, F11 steps into a procedure, and Shift + F11 steps out.
- Hover over variables, or use the Locals, Watch, and Immediate windows to inspect and even change values.
- Right-click a breakpoint to add a condition (
i = 500) or turn it into a tracepoint that logs a message without stopping. - Set the debugger to break when an exception is thrown (Exception Settings), not only when it's unhandled.
Debug and Trace output
Module Program
Sub Main()
Dim sw = Stopwatch.StartNew()
Dim total = 0L
For i = 1 To 1_000_000
total += i
Next
sw.Stop()
Debug.WriteLine($"loop took {sw.ElapsedMilliseconds} ms") ' only in Debug builds, to the debugger
Console.WriteLine(total)
Console.WriteLine($"measured: {sw.ElapsedTicks > 0}")
End Sub
End Module
500000500000
measured: True
Debug.WriteLine appears in Visual Studio's Output window and is
removed from Release builds. Stopwatch measures elapsed time. For
applications, use a real logging library (Microsoft.Extensions.Logging
or Serilog) that writes to files or a monitoring service.
Performance tips
Imports System.Text
Module Program
Sub Main()
' Slow: every & creates a new string
Dim s = ""
For i = 1 To 5
s &= i & ","
Next
Console.WriteLine(s)
' Fast for many pieces: StringBuilder
Dim sb As New StringBuilder()
For i = 1 To 5
sb.Append(i).Append(","c)
Next
Console.WriteLine(sb.ToString())
' Fast lookups: HashSet instead of List.Contains in a loop
Dim allowed As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase) From {"admin", "editor"}
Console.WriteLine(allowed.Contains("ADMIN"))
End Sub
End Module
1,2,3,4,5,
1,2,3,4,5,
True
- Measure first — with a profiler (Visual Studio's Diagnostic Tools, dotnet-trace, dotnet-counters) or BenchmarkDotNet — before optimizing.
- Use
Option Strict On: late binding onObjectis much slower than typed calls, and it hides bugs. - Pick the right collection (
Dictionary/HashSetfor lookups). - Use
AsyncI/O so threads aren't blocked waiting. - Build in Release mode (
dotnet build -c Release) before judging speed.
Reading a stack trace
When an exception reaches the top of a program, the stack trace lists the chain of calls, innermost first. In a Debug build it includes file names and line numbers — start reading at the first line that points into your code.