Liczniki wydajności w ADO.NET
ADO.NET 2.0 wprowadzono rozszerzoną obsługę liczników wydajności, które obejmują obsługę systemów i System.Data.SqlClient System.Data.OracleClient. Liczniki System.Data.SqlClient wydajności dostępne w poprzednich wersjach ADO.NET zostały przestarzałe i zastąpione nowymi licznikami wydajności omówionymi w tym temacie. Liczniki wydajności ADO.NET umożliwiają monitorowanie stanu aplikacji i używanych zasobów połączenia. Liczniki wydajności można monitorować przy użyciu monitor wydajności systemu Windows lub można uzyskać do tego dostępu programowo przy użyciu PerformanceCounter klasy w System.Diagnostics przestrzeni nazw.
Dostępne liczniki wydajności
Obecnie dostępnych jest 14 różnych liczników System.Data.SqlClient wydajności i System.Data.OracleClient zgodnie z opisem w poniższej tabeli. Należy pamiętać, że nazwy poszczególnych liczników nie są zlokalizowane w regionalnych wersjach programu Microsoft .NET Framework.
Licznik wydajności | opis |
---|---|
HardConnectsPerSecond |
Liczba połączeń na sekundę, które są wykonywane na serwerze bazy danych. |
HardDisconnectsPerSecond |
Liczba rozłączeń na sekundę, które są wykonywane na serwerze bazy danych. |
NumberOfActiveConnectionPoolGroups |
Liczba unikatowych grup puli połączeń, które są aktywne. Ten licznik jest kontrolowany przez liczbę unikatowych parametry połączenia znalezionych w domenie aplikacji. |
NumberOfActiveConnectionPools |
Łączna liczba pul połączeń. |
NumberOfActiveConnections |
Liczba aktywnych połączeń, które są obecnie używane. Uwaga: ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników poza domyślne. |
NumberOfFreeConnections |
Liczba połączeń dostępnych do użycia w pulach połączeń. Uwaga: ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników poza domyślne. |
NumberOfInactiveConnectionPoolGroups |
Liczba unikatowych grup puli połączeń oznaczonych do oczyszczania. Ten licznik jest kontrolowany przez liczbę unikatowych parametry połączenia znalezionych w domenie aplikacji. |
NumberOfInactiveConnectionPools |
Liczba nieaktywnych pul połączeń, które nie miały żadnych ostatnich działań i oczekują na likwidację. |
NumberOfNonPooledConnections |
Liczba aktywnych połączeń, które nie są w puli. |
NumberOfPooledConnections |
Liczba aktywnych połączeń zarządzanych przez infrastrukturę buforowania połączeń. |
NumberOfReclaimedConnections |
Liczba połączeń, które zostały odzyskane za pośrednictwem odzyskiwania pamięci, gdzie Close lub Dispose nie została wywołana przez aplikację. Nie jawne zamykanie lub usuwanie połączeń nie boli wydajności. |
NumberOfStasisConnections |
Liczba połączeń oczekujących na ukończenie akcji i dlatego jest niedostępna do użycia przez aplikację. |
SoftConnectsPerSecond |
Liczba aktywnych połączeń pobieranych z puli połączeń. Uwaga: ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników poza domyślne. |
SoftDisconnectsPerSecond |
Liczba aktywnych połączeń zwracanych do puli połączeń. Uwaga: ten licznik wydajności nie jest domyślnie włączony. Aby włączyć ten licznik wydajności, zobacz Aktywowanie liczników poza domyślne. |
Grupy puli połączeń i pule połączeń
W przypadku korzystania z uwierzytelniania systemu Windows (zintegrowane zabezpieczenia) należy monitorować zarówno liczniki wydajności, jak NumberOfActiveConnectionPoolGroups
i NumberOfActiveConnectionPools
. Przyczyną jest mapowanie grup puli połączeń na unikatowe parametry połączenia. W przypadku użycia zintegrowanych zabezpieczeń pule połączeń są mapowane na parametry połączenia i dodatkowo tworzą oddzielne pule dla poszczególnych tożsamości systemu Windows. Jeśli na przykład Fred i Julie, każdy w ramach tej samej domeny AppDomain, użyj parametry połączenia "Data Source=MySqlServer;Integrated Security=true"
, dla parametry połączenia zostanie utworzona grupa puli połączeń, a dwie dodatkowe pule zostaną utworzone, jedna dla Freda i jedna dla Julie. Jeśli Jan i Martha używają parametry połączenia z identycznym identyfikatorem logowania programu SQL Server, "Data Source=MySqlServer;User Id=lowPrivUser;Password=[PLACEHOLDER]"
dla tożsamości lowPrivUser zostanie utworzona tylko jedna pula.
Ważne
Firma Microsoft zaleca korzystanie z najbezpieczniejszego dostępnego przepływu uwierzytelniania. Jeśli łączysz się z usługą Azure SQL, tożsamości zarządzane dla zasobów platformy Azure to zalecana metoda uwierzytelniania.
Aktywowanie liczników poza domyślnymi
Liczniki NumberOfFreeConnections
wydajności , NumberOfActiveConnections
, SoftDisconnectsPerSecond
i SoftConnectsPerSecond
są domyślnie wyłączone. Dodaj następujące informacje do pliku konfiguracji aplikacji, aby je włączyć:
<system.diagnostics>
<switches>
<add name="ConnectionPoolPerformanceCounterDetail"
value="4"/>
</switches>
</system.diagnostics>
Pobieranie wartości licznika wydajności
Poniższa aplikacja konsolowa pokazuje, jak pobrać wartości liczników wydajności w aplikacji. Połączenia muszą być otwarte i aktywne, aby informacje zostały zwrócone dla wszystkich liczników wydajności ADO.NET.
Uwaga
W tym przykładzie użyto przykładowej bazy danych AdventureWorks dołączonej do programu SQL Server. Parametry połączenia podane w przykładowym kodzie zakładają, że baza danych jest zainstalowana i dostępna na komputerze lokalnym o nazwie wystąpienia SqlExpress oraz że utworzono identyfikatory logowania programu SQL Server zgodne z danymi podanymi w parametry połączenia. Może być konieczne włączenie identyfikatorów logowania programu SQL Server, jeśli serwer jest skonfigurowany przy użyciu domyślnych ustawień zabezpieczeń, które zezwalają tylko na uwierzytelnianie systemu Windows. Zmodyfikuj parametry połączenia zgodnie z potrzebami w twoim środowisku.
Przykład
Option Explicit On
Option Strict On
Imports System.Data.SqlClient
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Class Program
Private PerfCounters(9) As PerformanceCounter
Private connection As SqlConnection = New SqlConnection
Public Shared Sub Main()
Dim prog As Program = New Program
' Open a connection and create the performance counters.
prog.connection.ConnectionString = _
GetIntegratedSecurityConnectionString()
prog.SetUpPerformanceCounters()
Console.WriteLine("Available Performance Counters:")
' Create the connections and display the results.
prog.CreateConnections()
Console.WriteLine("Press Enter to finish.")
Console.ReadLine()
End Sub
Private Sub CreateConnections()
' List the Performance counters.
WritePerformanceCounters()
' Create 4 connections and display counter information.
Dim connection1 As SqlConnection = New SqlConnection( _
GetIntegratedSecurityConnectionString)
connection1.Open()
Console.WriteLine("Opened the 1st Connection:")
WritePerformanceCounters()
Dim connection2 As SqlConnection = New SqlConnection( _
GetSqlConnectionStringDifferent)
connection2.Open()
Console.WriteLine("Opened the 2nd Connection:")
WritePerformanceCounters()
Console.WriteLine("Opened the 3rd Connection:")
Dim connection3 As SqlConnection = New SqlConnection( _
GetSqlConnectionString)
connection3.Open()
WritePerformanceCounters()
Dim connection4 As SqlConnection = New SqlConnection( _
GetSqlConnectionString)
connection4.Open()
Console.WriteLine("Opened the 4th Connection:")
WritePerformanceCounters()
connection1.Close()
Console.WriteLine("Closed the 1st Connection:")
WritePerformanceCounters()
connection2.Close()
Console.WriteLine("Closed the 2nd Connection:")
WritePerformanceCounters()
connection3.Close()
Console.WriteLine("Closed the 3rd Connection:")
WritePerformanceCounters()
connection4.Close()
Console.WriteLine("Closed the 4th Connection:")
WritePerformanceCounters()
End Sub
Private Enum ADO_Net_Performance_Counters
NumberOfActiveConnectionPools
NumberOfReclaimedConnections
HardConnectsPerSecond
HardDisconnectsPerSecond
NumberOfActiveConnectionPoolGroups
NumberOfInactiveConnectionPoolGroups
NumberOfInactiveConnectionPools
NumberOfNonPooledConnections
NumberOfPooledConnections
NumberOfStasisConnections
' The following performance counters are more expensive to track.
' Enable ConnectionPoolPerformanceCounterDetail in your config file.
' SoftConnectsPerSecond
' SoftDisconnectsPerSecond
' NumberOfActiveConnections
' NumberOfFreeConnections
End Enum
Private Sub SetUpPerformanceCounters()
connection.Close()
Me.PerfCounters(9) = New PerformanceCounter()
Dim instanceName As String = GetInstanceName()
Dim apc As Type = GetType(ADO_Net_Performance_Counters)
Dim i As Integer = 0
Dim s As String = ""
For Each s In [Enum].GetNames(apc)
Me.PerfCounters(i) = New PerformanceCounter()
Me.PerfCounters(i).CategoryName = ".NET Data Provider for SqlServer"
Me.PerfCounters(i).CounterName = s
Me.PerfCounters(i).InstanceName = instanceName
i = (i + 1)
Next
End Sub
Private Declare Function GetCurrentProcessId Lib "kernel32.dll" () As Integer
Private Function GetInstanceName() As String
'This works for Winforms apps.
Dim instanceName As String = _
System.Reflection.Assembly.GetEntryAssembly.GetName.Name
' Must replace special characters like (, ), #, /, \\
Dim instanceName2 As String = _
AppDomain.CurrentDomain.FriendlyName.ToString.Replace("(", "[") _
.Replace(")", "]").Replace("#", "_").Replace("/", "_").Replace("\\", "_")
'For ASP.NET applications your instanceName will be your CurrentDomain's
'FriendlyName. Replace the line above that sets the instanceName with this:
'instanceName = AppDomain.CurrentDomain.FriendlyName.ToString.Replace("(", "[") _
' .Replace(")", "]").Replace("#", "_").Replace("/", "_").Replace("\\", "_")
Dim pid As String = GetCurrentProcessId.ToString
instanceName = (instanceName + ("[" & (pid & "]")))
Console.WriteLine("Instance Name: {0}", instanceName)
Console.WriteLine("---------------------------")
Return instanceName
End Function
Private Sub WritePerformanceCounters()
Console.WriteLine("---------------------------")
For Each p As PerformanceCounter In Me.PerfCounters
Console.WriteLine("{0} = {1}", p.CounterName, p.NextValue)
Next
Console.WriteLine("---------------------------")
End Sub
End Class
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Runtime.InteropServices;
class Program
{
PerformanceCounter[] PerfCounters = new PerformanceCounter[10];
SqlConnection connection = new SqlConnection();
static void Main()
{
Program prog = new Program();
// Open a connection and create the performance counters.
prog.connection.ConnectionString =
GetIntegratedSecurityConnectionString();
prog.SetUpPerformanceCounters();
Console.WriteLine("Available Performance Counters:");
// Create the connections and display the results.
prog.CreateConnections();
Console.WriteLine("Press Enter to finish.");
Console.ReadLine();
}
private void CreateConnections()
{
// List the Performance counters.
WritePerformanceCounters();
// Create 4 connections and display counter information.
SqlConnection connection1 = new SqlConnection(
GetIntegratedSecurityConnectionString());
connection1.Open();
Console.WriteLine("Opened the 1st Connection:");
WritePerformanceCounters();
SqlConnection connection2 = new SqlConnection(
GetSqlConnectionStringDifferent());
connection2.Open();
Console.WriteLine("Opened the 2nd Connection:");
WritePerformanceCounters();
SqlConnection connection3 = new SqlConnection(
GetSqlConnectionString());
connection3.Open();
Console.WriteLine("Opened the 3rd Connection:");
WritePerformanceCounters();
SqlConnection connection4 = new SqlConnection(
GetSqlConnectionString());
connection4.Open();
Console.WriteLine("Opened the 4th Connection:");
WritePerformanceCounters();
connection1.Close();
Console.WriteLine("Closed the 1st Connection:");
WritePerformanceCounters();
connection2.Close();
Console.WriteLine("Closed the 2nd Connection:");
WritePerformanceCounters();
connection3.Close();
Console.WriteLine("Closed the 3rd Connection:");
WritePerformanceCounters();
connection4.Close();
Console.WriteLine("Closed the 4th Connection:");
WritePerformanceCounters();
}
private enum ADO_Net_Performance_Counters
{
NumberOfActiveConnectionPools,
NumberOfReclaimedConnections,
HardConnectsPerSecond,
HardDisconnectsPerSecond,
NumberOfActiveConnectionPoolGroups,
NumberOfInactiveConnectionPoolGroups,
NumberOfInactiveConnectionPools,
NumberOfNonPooledConnections,
NumberOfPooledConnections,
NumberOfStasisConnections
// The following performance counters are more expensive to track.
// Enable ConnectionPoolPerformanceCounterDetail in your config file.
// SoftConnectsPerSecond
// SoftDisconnectsPerSecond
// NumberOfActiveConnections
// NumberOfFreeConnections
}
private void SetUpPerformanceCounters()
{
connection.Close();
this.PerfCounters = new PerformanceCounter[10];
string instanceName = GetInstanceName();
Type apc = typeof(ADO_Net_Performance_Counters);
int i = 0;
foreach (string s in Enum.GetNames(apc))
{
this.PerfCounters[i] = new PerformanceCounter();
this.PerfCounters[i].CategoryName = ".NET Data Provider for SqlServer";
this.PerfCounters[i].CounterName = s;
this.PerfCounters[i].InstanceName = instanceName;
i++;
}
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern int GetCurrentProcessId();
private string GetInstanceName()
{
//This works for Winforms apps.
string instanceName =
System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
// Must replace special characters like (, ), #, /, \\
string instanceName2 =
AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(', '[')
.Replace(')', ']').Replace('#', '_').Replace('/', '_').Replace('\\', '_');
// For ASP.NET applications your instanceName will be your CurrentDomain's
// FriendlyName. Replace the line above that sets the instanceName with this:
// instanceName = AppDomain.CurrentDomain.FriendlyName.ToString().Replace('(','[')
// .Replace(')',']').Replace('#','_').Replace('/','_').Replace('\\','_');
string pid = GetCurrentProcessId().ToString();
instanceName = instanceName + "[" + pid + "]";
Console.WriteLine("Instance Name: {0}", instanceName);
Console.WriteLine("---------------------------");
return instanceName;
}
private void WritePerformanceCounters()
{
Console.WriteLine("---------------------------");
foreach (PerformanceCounter p in this.PerfCounters)
{
Console.WriteLine("{0} = {1}", p.CounterName, p.NextValue());
}
Console.WriteLine("---------------------------");
}
}