Memory-Leaks in ADO.NET mit NumberOfReclaimedConnections protokollieren

Eine Bibliothek von mir macht irgendwie Connections falsch zu.

Selbst mit ANTS Memory Profiler bin ich nicht so richtig weiter gekommen, um zu sehen, ob meine Annahme mit den nicht geschlossenen Connections überhaupt zutrifft.

Dann bin ich auf den Leistungsindikator (englisch „Performance Counters“) gestossen, der mir hilft: NumberOfReclaimedConnections. MSDN schreibt:

The number of connections that have been reclaimed through garbage collection where Close or Dispose was not called by the application. Not explicitly closing or disposing connections hurts performance.

In Deutsch:

Anzahl der Verbindungen, die durch die Garbage Collection (automatische Speicherbereinigung) wieder verfügbar gemacht wurden, bei denen die Anwendung weder Close noch Dispose aufgerufen hat. Nicht mehr benötigte Verbindungen, die weiterbestehen, weil sie nicht explizit geschlossen oder gelöscht wurden, beeinträchtigen die Arbeitsgeschwindigkeit.

Den wollte ich also analysieren. Ich bin gescheitert, dies via Leitungsüberwachung-MMC-Tool zu machen und fand auch keine konkreten Code-Beispiele um in der Anwendung selbst den Counter auszulesen.

Also habe ich selbst Code geschrieben, der auf meinem deutschen Windows auch funktioniert:

private static void logPerfCounter()
{
    var ina = new PerformanceCounterCategory(
        @".NET-Datenanbieter für SqlServer").GetInstanceNames();

    var pc = new PerformanceCounter
    {
        CategoryName = @".NET-Datenanbieter für SqlServer",
        CounterName = @"NumberOfReclaimedConnections",
        InstanceName =
            ina.FirstOrDefault(
                n =>
                    n.ToLowerInvariant()
                        .StartsWith(Assembly.GetEntryAssembly()
                            .GetName().Name.ToLowerInvariant()))
    };

    var nv = pc.NextValue();
    Console.Write(@" {0} ", nv);
}

Damit konnte ich dann verifizieren, dass über die Zeit hinweg der Counter stets gewachsen ist und nie gesunken.

In einer anderen Vergleichs-App war der Wert stets 0, dort habe ich die Connections also korrekt geschlossen bzw. via Dispose-Aufrufe (oder implizit via using) freigegeben.