Contadores de desempenho em ADO.NET
ADO.NET 2.0 introduziu suporte expandido para contadores de desempenho que inclui suporte para ambos e System.Data.SqlClient System.Data.OracleClient. Os System.Data.SqlClient contadores de desempenho disponíveis em versões anteriores do ADO.NET foram preteridos e substituídos pelos novos contadores de desempenho discutidos neste tópico. Você pode usar contadores de desempenho ADO.NET para monitorar o status do seu aplicativo e os recursos de conexão que ele usa. Os contadores de desempenho podem ser monitorados usando o System.Diagnostics Monitor de Desempenho do Windows ou podem ser acessados programaticamente usando a PerformanceCounter classe no namespace.
Contadores de desempenho disponíveis
Atualmente, existem 14 contadores de desempenho diferentes disponíveis para System.Data.SqlClient e System.Data.OracleClient conforme descrito na tabela a seguir. Observe que os nomes para os contadores individuais não estão localizados em versões regionais do Microsoft .NET Framework.
Contador de desempenho | Description |
---|---|
HardConnectsPerSecond |
O número de conexões por segundo que estão sendo feitas a um servidor de banco de dados. |
HardDisconnectsPerSecond |
O número de desconexões por segundo que estão sendo feitas em um servidor de banco de dados. |
NumberOfActiveConnectionPoolGroups |
O número de grupos de pool de conexões exclusivos que estão ativos. Esse contador é controlado pelo número de cadeias de conexão exclusivas encontradas no AppDomain. |
NumberOfActiveConnectionPools |
O número total de pools de conexões. |
NumberOfActiveConnections |
O número de conexões ativas que estão atualmente em uso. Nota: Este contador de desempenho não está ativado por predefinição. Para habilitar esse contador de desempenho, consulte Ativando contadores desativados por padrão. |
NumberOfFreeConnections |
O número de conexões disponíveis para uso nos pools de conexões. Nota: Este contador de desempenho não está ativado por predefinição. Para habilitar esse contador de desempenho, consulte Ativando contadores desativados por padrão. |
NumberOfInactiveConnectionPoolGroups |
O número de grupos de pool de conexões exclusivos marcados para poda. Esse contador é controlado pelo número de cadeias de conexão exclusivas encontradas no AppDomain. |
NumberOfInactiveConnectionPools |
O número de pools de conexões inativas que não tiveram nenhuma atividade recente e estão aguardando para serem descartados. |
NumberOfNonPooledConnections |
O número de conexões ativas que não estão agrupadas. |
NumberOfPooledConnections |
O número de conexões ativas que estão sendo gerenciadas pela infraestrutura do pool de conexões. |
NumberOfReclaimedConnections |
O número de conexões que foram recuperadas por meio da coleta de lixo onde Close ou Dispose não foi chamado pelo aplicativo. Não fechar ou descartar conexões explicitamente prejudica o desempenho. |
NumberOfStasisConnections |
O número de conexões atualmente aguardando a conclusão de uma ação e que, portanto, não estão disponíveis para uso pelo seu aplicativo. |
SoftConnectsPerSecond |
O número de conexões ativas que estão sendo extraídas do pool de conexões. Nota: Este contador de desempenho não está ativado por predefinição. Para habilitar esse contador de desempenho, consulte Ativando contadores desativados por padrão. |
SoftDisconnectsPerSecond |
O número de conexões ativas que estão sendo retornadas ao pool de conexões. Nota: Este contador de desempenho não está ativado por predefinição. Para habilitar esse contador de desempenho, consulte Ativando contadores desativados por padrão. |
Grupos de Pool de Conexões e Pools de Conexões
Ao usar a Autenticação do Windows (segurança integrada), você deve monitorar os contadores e NumberOfActiveConnectionPools
de NumberOfActiveConnectionPoolGroups
desempenho. O motivo é que os grupos do pool de conexões são mapeados para cadeias de conexão exclusivas. Quando a segurança integrada é usada, os pools de conexões são mapeados para cadeias de conexão e, adicionalmente, criam pools separados para identidades individuais do Windows. Por exemplo, se Fred e Julie, cada um dentro do mesmo AppDomain, ambos usarem a cadeia de conexão "Data Source=MySqlServer;Integrated Security=true"
, um grupo de pool de conexões será criado para a cadeia de conexão e dois pools adicionais serão criados, um para Fred e outro para Julie. Se John e Martha usarem uma cadeia de conexão com um logon idêntico do SQL Server, "Data Source=MySqlServer;User Id=lowPrivUser;Password=[PLACEHOLDER]"
somente um único pool será criado para a identidade lowPrivUser .
Importante
A Microsoft recomenda que você use o fluxo de autenticação mais seguro disponível. Se você estiver se conectando ao SQL do Azure, as Identidades Gerenciadas para recursos do Azure serão o método de autenticação recomendado.
Ativando contadores desativados por padrão
Os contadores de desempenho , , NumberOfActiveConnections
SoftDisconnectsPerSecond
e SoftConnectsPerSecond
estão desativados NumberOfFreeConnections
por padrão. Adicione as seguintes informações ao arquivo de configuração do aplicativo para habilitá-los:
<system.diagnostics>
<switches>
<add name="ConnectionPoolPerformanceCounterDetail"
value="4"/>
</switches>
</system.diagnostics>
Recuperando valores do contador de desempenho
O aplicativo de console a seguir mostra como recuperar valores de contador de desempenho em seu aplicativo. As conexões devem estar abertas e ativas para que as informações sejam retornadas para todos os contadores de desempenho ADO.NET.
Nota
Este exemplo usa o banco de dados AdventureWorks de exemplo incluído no SQL Server. As cadeias de conexão fornecidas no código de exemplo pressupõem que o banco de dados está instalado e disponível no computador local com um nome de instância de SqlExpress e que você criou logons do SQL Server que correspondem aos fornecidos nas cadeias de conexão. Talvez seja necessário habilitar logons do SQL Server se o servidor estiver configurado usando as configurações de segurança padrão que permitem apenas a Autenticação do Windows. Modifique as cadeias de conexão conforme necessário para se adequar ao seu ambiente.
Exemplo
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("---------------------------");
}
}