Skip to content
AgileLogics
6 min read

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 on Object is much slower than typed calls, and it hides bugs.
  • Pick the right collection (Dictionary/HashSet for lookups).
  • Use Async I/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.