Speed SQL

Ajustando chamadas de banco de dados com a criação de perfil de interação de camada

Mark Friedman

Muitos aplicativos são criados explicitamente para usar várias camadas, onde o desempenho das chamadas na camada de acesso a dados é essencial para a capacidade de resposta do aplicativo. O uso de várias camadas aumenta a flexibilidade do aplicativo. A abordagem com n camadas também favorece o isolamento dos principais componentes, o que pode ser usado para aprimorar a confiabilidade e a escalabilidade. O uso de várias camadas promove a escalabilidade, pois os componentes isolados em camadas distintas podem ser distribuídos mais prontamente para os recursos de computação disponíveis.

A TIP (Criação de perfil de interação de camada) foi desenvolvida para ajudar você a entender o desempenho da camada de dados utilizada pelo aplicativo. A TIP é um novo recurso das ferramentas de criação de perfil do Visual Studio; ela mede e relata a duração dos atrasos da camada de dados sofridos pelos aplicativos .NET Framework quando aguardam a conclusão de chamadas síncronas para bancos de dados compatíveis com ADO.NET. Para os aplicativos orientados a tempo de resposta, que fazem chamadas frequentes para bancos de dados, a TIP ajuda você a compreender quais solicitações de dados contribuem mais para atrasos na resposta.

Neste artigo, apresentarei a você a TIP e demonstrarei seus recursos de relatório. Também discutirei a tecnologia de instrumentação utilizada pela TIP e fornecerei algumas das melhores práticas para utilizar a TIP de forma eficaz para diagnosticar problemas de desempenho relacionados à atividade do banco de dados. Passaremos pela utilização da TIP em um aplicativo Web ASP.NET de exemplo, com duas camadas e uso intensivo de dados, que acessa os dados do Microsoft SQL Server usando a tecnologia LINQ to SQL. Finalmente, discutirei como você pode aumentar os dados de desempenho da TIP usando as ferramentas padrão de desempenho do Administrador do SQL para uma compreensão mais aprofundada do desempenho de uma camada de dados.

Introdução à TIP

A TIP adiciona dinamicamente o código de instrumentação para medir a duração de chamadas para a camada de dados do aplicativo durante a execução de uma criação de perfil. As ferramentas de criação de perfil do Visual Studio estão disponíveis no Visual Studio 2010 Premium Edition e no Visual Studio 2010 Ultimate Edition.

Para iniciar uma sessão de criação de perfil, você pode clicar em Launch Performance Wizard no menu Analyze, clicar em Start Performance Analysis no menu Debug ou usar o atalho de teclado Alt+F2. A primeira página do Performance Wizard solicita que você selecione um método de criação de perfil.

A TIP pode ser usada com qualquer método de criação de perfil (amostragem, instrumentação, memória ou simultaneidade), mas não é habilitada por padrão. Para habilitar a TIP, será necessário desmarcar a caixa de seleção “Launch profiling after the wizard finishes” na página 3 do Performance Wizard (como a TIP ainda não está ativada, você não está pronto para iniciar o aplicativo e a criação de perfil). Para obter melhores resultados, recomendo selecionar inicialmente o método de amostragem da criação de perfil, principalmente se você estiver mais preocupado com os dados de interação da camada de dados. Isso porque a amostragem tem menos impacto no desempenho do aplicativo.

Para habilitar a coleta de dados da TIP, no Performance Wizard, acesse a Performance Session que acabou de ser criada na janela Performance Explorer e clique com o botão direito do mouse para ver suas propriedades. Na caixa de diálogo de propriedades, selecione a guia Tier Interactions e marque a caixa de seleção "Enable tier interaction profiling". Clique no botão OK para fechar a caixa de diálogo. Agora que a TIP está habilitada, você está pronto para iniciar a criação de perfil do aplicativo.

Para iniciar realmente a execução da criação de perfil, clique no botão Launch with Profiling da barra de ferramentas, na janela Performance Explorer.

Para obter instruções completas sobre como habilitar a TIP no Visual Studio, consulte a postagem do blog de Habib Heydarian intitulada “Passo a passo: Usando a criação de perfil de interação de camada no Visual Studio Team System 2010”, em https://blogs.msdn.com/b/habibh/archive/2009/06/30/walkthrough-using-the-tier-interaction-profiler-in-visual-studio-team-system-2010.aspx.

Como a TIP mede o desempenho

A TIP insere o código no aplicativo durante uma execução de criação de perfil que mede as chamadas para a camada de dados do ADO.NET utilizada pelo aplicativo. Quando a criação de perfil de interação de camada está ativa, o Visual Studio Profiler inspeciona a MSIL (Microsoft Intermediate Language) da solução, procurando referências às funções do ADO.NET. Antes de chamar o compilador JIT (Just-In-Time) para gerar o código nativo executado pelo aplicativo, o criador de perfil insere instruções que adicionam instrumentação aos principais métodos do ADO.NET. Esse código de instrumentação mantém o controle do tempo gasto durante cada chamada do ADO.NET.

Durante a execução do aplicativo, a TIP captura e registra os dados de tempo. Quando o perfil do aplicativo está sendo criado, essa instrumentação registra a duração de quaisquer chamadas do ADO.NET feitas, e também captura uma cópia do texto do comando usado na chamada de banco de dados. Durante a execução do aplicativo, são coletados dados de tempo de todos os acessos a banco de dados executados com métodos síncronos das classes do ADO.NET, inclusive APIs do SQL, OLE DB, ODBC (Open Database Connectivity) e SQL Server Compact (SQL CE). A TIP também irá capturar dados de tempo se o aplicativo utilizar APIs do LINQ to SQL ou Entity Framework para acessar bancos de dados SQL.

Os dados de tempo são armazenados com outros dados coletados durante a sessão de criação de perfil em um arquivo .vsp. Uma vez que um aplicativo que faz uma chamada para um banco de dados externo executa uma chamada fora do processo, as instruções que a TIP adiciona para instrumentar o aplicativo influenciam muito pouco o desempenho geral do aplicativo.

Ajustando para o desempenho

Um padrão de design comum envolve a divisão de um aplicativo Web em uma camada de apresentação, uma camada de lógica de negócios e uma camada de dados. Esse paradigma do design leva à divisão do aplicativo em componentes para promover a confiabilidade, a extensibilidade e a escalabilidade. O aplicativo de várias camadas acessa sua camada de dados usando componentes de lógica de negócios que referenciam entidades de dados logicamente como linhas e colunas em um conjunto de tabelas relacionado. A maneira como um banco de dados como o SQL Server mantém os dados físicos associados às tabelas de banco de dados é transparente para o aplicativo, por design.

Em prol da confiabilidade e da escalabilidade, os aplicativos Web de grande escala com frequência configuram vários computadores em pools que são responsáveis pelo processamento da lógica associada a cada camada do aplicativo. O fato de vários computadores darem suporte a várias camadas cria um desafio especial na análise de desempenho, pois o monitoramento de qualquer computador fornece uma visão incompleta do aplicativo.

Por exemplo, o uso de um sistema de banco de dados como o SQL Server para gerenciar e mediar o acesso ao repositório de dados do aplicativo cria uma camada de dados isolada da lógica do aplicativo. Os dados do aplicativo hospedados em um banco de dados como o SQL Server são mantidos em um espaço de endereço de processo separado, com seu próprio repositório de dados. O banco de dados que contém os dados do aplicativo pode residir no mesmo computador físico que o aplicativo, porém é mais provável que ele seja acessado de outro computador com o uso de protocolos de rede.

Os comandos do SQL passados pelo aplicativo para um banco de dados externo e que são operados lá são chamadas fora do processo. Os perfis de amostragem verificam que o aplicativo está inativo enquanto aguarda a conclusão dessas chamadas fora do processo, mas não podem informar por que o aplicativo está aguardando, nem a duração desses atrasos. Os perfis instrumentados e de simultaneidade medem a duração desses atrasos, mas não podem informar quais comandos do SQL estão sendo emitidos ou por que estão demorando tanto para serem concluídos.

Em aplicativos de várias camadas que se comunicam com um banco de dados externo, o componente de banco de dados frequentemente é um colaborador principal do tempo de resposta geral do aplicativo. Entre as ferramentas de criação de perfil do Visual Studio estão vários métodos de criação de perfil que incluem amostragem, instrumentação, alocação de memória e simultaneidade, mas nenhum desses métodos pode ajudar muito na identificação de problemas de desempenho associados ao acesso de um banco de dados externo sem dados da TIP.

Os dados da TIP permitem fazer busca detalhada nos atrasos relacionados a banco de dados e compreender porque eles ocorrem. Em conjunto com outras ferramentas de desempenho que o fornecedor do banco de dados pode oferecer, você também pode começar a entender o que pode ser feito para aprimorar o desempenho de um aplicativo que depende intensamente do desempenho do banco de dados.

Como a TIP adiciona instrumentação ao código do aplicativo, os dados de tempo associados aos comandos de banco de dados podem ser coletados independentemente da localização física da instância do banco de dados que está sendo acessada. Os dados de tempo podem ser coletados, por exemplo, para chamadas fora do processo para uma instância do SQL Server residente fisicamente no mesmo computador que o aplicativo, o que é um cenário típico em teste de unidade. Quando o mesmo aplicativo está pronto para teste de integração ou de carga em uma instância do SQL Server localizada em um computador físico separado, a TIP pode continuar a coletar dados de medidas para essa configuração. De fato, as medidas da TIP permitem comparar o desempenho dessas duas configurações diferentes.

A TIP permite comparar o impacto das muitas opções de desempenho e ajuste do banco de dados externo que estão disponíveis, inclusive configuração da memória cache, dispositivos físicos de armazenamento de dados, particionamento de banco de dados, indexação de banco de dados e design de tabela de banco de dados. Além disso, é possível medir diretamente o impacto do desempenho da execução do SQL Server em uma máquina virtual.

Noções básicas da TIP

Quando uma sessão de criação de perfil com a TIP ativada é concluída, os dados de tempo associados a qualquer interação do aplicativo com a camada de dados do ADO.NET são resumidos na exibição Tier Interactions. A Figura 1 mostra um exemplo do criador de perfil quando a coleta de dados da TIP está ativa e existe atividade no ADO.NET durante a execução da criação de perfil.

Figura 1 Um relatório de interação do criador de perfil do Visual Studio

A metade superior do relatório é um resumo dos dados de criação de perfil coletados. Para aplicativos ASP.NET. a exibição é organizada por URL. O relatório agrupa o tempo de resposta do servidor, de solicitações GET do aplicativo Web, por URL.

Abaixo da camada do aplicativo, o relatório mostra cada conexão com uma camada do banco de dados (que neste exemplo era o banco de dados de exemplo AdventureWorks). Ele mede e relata a parte do tempo de processamento do servidor para solicitações ASP.NET associadas a chamadas de banco de dados síncronas com o uso do ADO.NET. Nesse exemplo aparecem três linhas de resumo, cada uma tabulando a atividade do banco de dados associada a três diferentes páginas ASP.NET no site cujo perfil está sendo criado. Para cada página ASP.NET identificada durante a criação de perfil, são relatados o número de solicitações do ASP.NET processadas durante a execução da criação de perfil e os tempos de resposta do servidor para cada mensagem de resposta gerada.

Linhas de resumo adicionais mostram dados de tempo de resposta de outras solicitações GET, inclusive solicitações de folhas de estilo, código JavaScript e imagens vinculadas nas páginas. As chamadas de banco de dados que o criador de perfil não consegue associar a uma solicitação específica do ASP.NET são agrupadas na categoria Other Requests.

Quando você está criando o perfil de um aplicativo de área de trabalho ou de console do Windows que utiliza uma camada de dados, o relatório organiza a atividade do ADO.NET sob o nome do processo.

Abaixo de cada linha de resumo de página da Web existe uma única linha de resumo que relata o número de solicitações de banco de dados síncronas, organizadas por conexão de banco de dados, que foram feitas durante o processamento do ASP.NET. Nesse exemplo é possível ver que foram manipuladas seis solicitações do ASP.NET para Customer­Query.aspx em uma única conexão de banco de dados. Essas seis solicitações exigiram no total 0,959 segundos para serem processadas no servidor, para um tempo médio de resposta de 160 milissegundos. Essas solicitações emitiram 12 consultas SQL que exigiram aproximadamente 45 milissegundos para serem concluídas. A espera pelas solicitações do banco de dados foi responsável por apenas cerca de 5% do tempo decorrido, associada à geração de mensagens de resposta para essa página da Web.

Se você realçar uma das linhas do resumo de conexão de banco de dados, a metade inferior da exibição Tier Interactions mostrará os comandos SQL específicos emitidos pelo aplicativo. Os comandos SQL são agrupados pelo texto de comando emitido e classificados por tempo decorrido no grupo de páginas.

No exemplo, um comando SQL foi emitido três vezes, outro foi emitido seis vezes e um terceiro foi emitido três vezes. Na exibição de detalhes, o tempo decorrido de cada consulta específica, acumulado em uma única linha no relatório resumido, é relatado separadamente. Você pode ver o tempo total decorrido, a média de todas as instâncias do comando e os atrasos mínimo e máximo observados em cada consulta.

Se você clicar duas vezes na linha de detalhes do comando SQL, o texto completo do comando SQL que foi emitido será exibido em uma janela Database Command Text. Esse é o comando real que o aplicativo passou para o banco de dados pela interface do ADO.NET durante a execução. Se a solicitação for para execução de um procedimento armazenado, a chamada específica para o procedimento armazenado será exibida.

Um exemplo de LINQ to SQL

Vejamos um exemplo simples do uso da TIP para compreender um aplicativo ASP.NET que depende intensamente do acesso a informações de um banco de dados.

A TIP pode ser útil especialmente com aplicativos que utilizam LINQ to SQL para acessar dados armazenados em um banco de dados externo do SQL Server, pois a LINQ tende a remover o desenvolvedor uma etapa à frente do banco de dados físico e de suas características de desempenho. Com o LINQ to SQL, os diagramas E:R (Entity:Relationship) que você cria no Object Relational Designer geram classes que são usadas pelo Visual Studio como modelos para criar automaticamente os comandos SQL sintaticamente corretos.

Como o LINQ to SQL elimina a maioria das considerações de codificação da linguagem SQL e é fácil de usar, ele também tende a mascarar considerações de desempenho importantes associadas a design de banco de dados, configuração e ajuste. Como ilustra esse exemplo, com a LINQ, é possível criar facilmente uma consulta complexa que une várias tabelas, sem precisar considerar as implicações de desempenho desse processo.

Com a TIP, é possível ver o texto real do comando SQL gerado pelo LINQ to SQL, bem como coletar medidas da execução dessas consultas SQL, em tempo de execução. Com o texto do comando SQL em mãos, é possível acessar outras ferramentas de ajuste do banco de dados para ajudar você a compreender melhor as implicações de desempenho de qualquer operação do LINQ to SQL em particular.

Meu exemplo é um aplicativo de Web Form que consulta tabelas Sales.Customer do Adventure­Works usando uma ID de cliente específica para recuperar o histórico de pedidos desse cliente. Entre as tabelas do AdventureWorks envolvidas nessa consulta estão Customer, SalesOrderHeader, Sales­OrderDetail e StateProvince, como ilustra a exibição Object Relational Designer na Figura 2.

Figura 2 Tabelas do AdventureWorks usadas para consultar informações de Sales.Customer

Se você desejar exibir também as informações de endereço para correspondência e endereço de email do cliente junto com o histórico do pedido, as tabelas Customer­Address, Address e Contact precisarão ser acessadas. Como mostra o Object Relational Designer, as tabelas do AdventureWorks contêm chaves primárias e estrangeiras, como CustomerID, SalesOrder e ContactID, que permitem que essas tabelas sejam unidas logicamente.

O código C# para criar uma consulta de cliente do AdventureWorks usando LINQ to SQL é mostrado na Figura 3. Nesse caso, custid é o valor CustomerID específico solicitado. Essa consulta retorna uma coleção customeryquery que contém uma única linha de dados com os campos de dados listados na cláusula select new.

Figura 3 Consulta de cliente to LINQ to SQL

var customerquery = 
  from customers in db.Customers
  from custaddrs in db.CustomerAddresses
  from addrs in db.Addresses
  where (customers.CustomerID == custid &&
         customers.CustomerID == custaddrs.CustomerID &&
         custaddrs.AddressID == addrs.AddressID)

  select new {
    customers.CustomerID,
    customers.CustomerType,
    addrs.AddressLine1,
    addrs.AddressLine2,
    addrs.City,
    addrs.StateProvince,
    addrs.PostalCode,
    customers.TerritoryID
  };

A customeryquery pode então ser associada a um controle em uma página da Web do ASP.NET:

DetailsView1.DataSource = customerquery;
DetailsView1.DataBind();

Agora posso criar uma consulta para recuperar o histórico de pedidos desse cliente:

var orderquery = 
  from orderhdr in db.SalesOrderHeaders
  where (orderhdr.CustomerID == custid)
  orderby orderhdr.OrderDate
  select new {
    Date = orderhdr.OrderDate.ToShortDateString(),
    orderhdr.AccountNumber,
    InvoiceNo = orderhdr.SalesOrderID,
    orderhdr.TotalDue
  };

Quando essa operação do LINQ to SQL for executada, orderquery conterá uma linha correspondente a cada linha da tabela OrderHdr associada a uma Customer ID específica. A coleção orderquery conterá várias linhas se o histórico do cliente indicar que havia várias transações de vendas.

Essas consultas parecem simples superficialmente. Porém, usando a TIP, é possível começar a entender as implicações do desempenho dessas operações do LINQ to SQL que são aparentemente simples.

Usando dados da TIP para ajuste

Vamos examinar melhor a customerquery. Em tempo de execução, o LINQ to SQL usa as operações SELECT do banco de dados lógico implícitas na instrução LINQ para gerar um comando SQL válido que une dados de quatro tabelas do AdventureWorks: Customers, Customer­Addresses, Addresses e a tabela estática StateProvince. Você não vê essas tabelas aqui no código do LINQ to SQL.

Quando você executa esse código no criador de perfil do Visual Studio, a instrumentação da TIP relata o número de vezes que essa consulta foi executada e mede o tempo de atraso da página da Web ao aguardar sua execução. Essa é de fato a operação que foi executada seis vezes durante a execução da criação de perfil ilustrada na Figura 1.

Além disso, como visto anteriormente, o comando SQL gerado pelo código do LINQ to SQL também está disponível quando o perfil do aplicativo é criado. A Figura 4 mostra o comando SQL real dessa operação.

Figura 4 Comando SQL para customerquery

SELECT [t0].[CustomerID], [t0].[CustomerType], [t2].[AddressLine1], [t2].[AddressLine2],
 [t2].[City], [t3].[StateProvinceID], [t3].[StateProvinceCode], [t3].[CountryRegionCode], 
[t3].[IsOnlyStateProvinceFlag], [t3].[Name], [t3].[TerritoryID], [t3].[rowguid],
 [t3].[ModifiedDate], [t2].[PostalCode], [t0].[TerritoryID] AS [TerritoryID2]
FROM [Sales].[Customer] AS [t0]
CROSS JOIN [Sales].[CustomerAddress] AS [t1]
CROSS JOIN [Person].[Address] AS [t2]
INNER JOIN [Person].[StateProvince] AS [t3] ON [t3].[StateProvinceID] = [t2].[StateProvinceID]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = [t1].[CustomerID]) AND
 ([t1].[AddressID] = [t2].[AddressID])

Observe que o texto do comando SQL inclui um token (designado aqui como “@p0”) para representar o parâmetro ID do cliente que a LINQ insere na consulta.

Agora que o texto real do comando SQL gerado pela LINQ está disponível, é possível compreender como o design do banco de dados está afetando o desempenho da consulta.

Uma coisa que você pode fazer é executar esse comando SQL no SQL Server Management Studio e examinar seu plano de execução, como mostra a Figura 5. Para acessar o plano de execução dessa consulta, é necessário adicionar um comando que aponte para o banco de dados apropriado:

USE AdventureWorks ;
GO

Em seguida, copie o texto do comando SQL do relatório da TIP, lembrando-se de substituir o token “@p0” por uma CustomerID válida do banco de dados. Depois execute essa consulta de exemplo no SQL Server Management Studio e acesse o plano de execução que mostra como o otimizador de consulta converteu a solicitação lógica em um plano de execução físico.

Figura 5 Plano de execução da operação de exemplo do LINQ to SQL

Nesse exemplo, o plano de execução da consulta mostra que a instrução SELECT acessou a tabela Customer usando um índice clusterizado no campo CustomerID que retornou exatamente uma linha na tabela. No SQL Server Management Studio, é possível usar o mouse para focalizar uma operação e exibir suas propriedades, ou realçar a operação e clicar com o botão direito do mouse para exibir a janela Properties. Dessa forma, você pode percorrer cada uma das operações restantes solicitadas pelo comando. Cada um dos três JOINs subsequentes que aumentam o Customer SELECT inicial acessa uma tabela usando seu índice clusterizado e retorna uma única linha exclusiva.

Nessa investigação é possível ver que, para processar essa consulta, é necessário acessar ao todo quatro linhas, cada uma de uma tabela diferente no banco de dados AdventureWorks. Cada acesso é executado com eficiência utilizando a chave primária exclusiva da tabela.

Da mesma forma, você pode usar a TIP para ver o comando SQL do código orderquery e alimentá-lo no SQL Server Management Studio para ver seu plano de execução (veja a Figura 6). Essa consulta acessa uma única tabela chamada OrderHdr usando a CustomerID como uma chave estrangeira, então ela precisa acessar um índice não clusterizado comum, bem como o índice clusterizado em SalesOrderHeaderID.

Figura 6 Plano de execução de orderquery

Esta instância específica da consulta retorna nove linhas. A cláusula orderby no código do LINQ to SQL é convertida em uma cláusula SQL ORDER BY que envolve uma operação Sort adicional no resultset da instrução SELECT. Essa operação representa 40% do custo geral de execução da solicitação, conforme estimativa do SQL Server Plan Optimizer.

Escolhendo um contexto de criação de perfil

A TIP foi desenvolvida para complementar os métodos de criação de perfil existentes do Visual Studio para coletar medidas específicas em interações da camada de dados. A TIP é um recurso secundário de coleta de dados e não pode ser coletada sem a especificação de um método de criação de perfil primário. Os dados da TIP podem ser coletados durante a execução de amostragem, instrumentação e criação de perfil de simultaneidade para qualquer aplicativo que se comunique com uma camada de dados usando o ADO.NET.

Considerando a necessidade de escolher um método primário de criação de perfil para um aplicativo para o qual você deseja coletar dados da TIP, qual método você deve usar? Vamos verificar algumas das considerações da escolha de um método primário de criação de perfil.

Os atrasos associados a interações da camada de dados são o foco principal da investigação de desempenho? Se forem, a criação de perfil de amostragem é o método primário recomendado, pois em geral é a forma de criação de perfil menos invasiva.

Se os atrasos da camada de dados não forem o foco principal da investigação de desempenho, escolha um método de criação de perfil com base no item com maior probabilidade de fornecer os dados de medida mais aplicáveis no contexto atual. Por exemplo, se você estiver investigando um problema associado à execução simultânea de vários threads, colete dados de simultaneidade. Se estiver investigando um problema associado a um aplicativo associado à CPU, colete dados de amostragem. Para obter orientação adicional sobre qual método de coleta primário escolher, consulte o artigo “Como escolher métodos de coleta”.

Caso você não esteja familiarizado com o código da camada de dados, talvez precise de ajuda dos dados de criação de perfil primários para localizar o código exato que dá origem a essas chamadas do ADO.NET. A TIP não captura uma pilha de chamadas quando coleta informações de tempo em chamadas síncronas fora do processo do ADO.NET. Se você precisar entender em que local do aplicativo as chamadas para métodos do ADO.NET são feitas, os perfis instrumentados serão muito úteis. Os dados de amostragem também podem ajudar você a fazer isso, porém não com a precisão de um perfil instrumentado.

Você pode optar por coletar dados de contenção de recursos juntamente com as medidas de interação de camada, mas a coleta de dados de contenção tende a ser uma função com mais sobrecarga do que a amostragem, e os dados de contenção provavelmente não fornecem nenhuma assistência para ajudar a determinar a origem de chamadas específicas do ADO.NET. As investigações que requerem a criação de perfil de alocação de memória do .NET, que geralmente são de altíssimo impacto, provavelmente não se beneficiam com a coleta de medidas de interação de camada.

Perfis de amostragem

Com frequência, as próprias interações da camada de dados são o foco principal de uma investigação de desempenho. Nesse caso, os melhores resultados geralmente são obtidos quando a amostragem é escolhida como o método primário de criação de perfil. A amostragem é preferida nesse caso, principalmente por ser o método de criação de perfil que em geral menos afeta o desempenho de um aplicativo. Os perfis de amostragem também podem se mostrar úteis na navegação para o código-fonte onde têm origem as chamadas do ADO.NET que mais afetam o desempenho.

Com as funções da camada de dados executadas fora do processo, as amostras de execução de instrução coletadas durante um perfil de amostragem geralmente não refletem o tempo que um aplicativo esperou pela conclusão de chamadas síncronas através da interface do ADO.NET. Durante os períodos em que o thread de execução de um aplicativo está aguardando a conclusão dessas chamadas fora do processo, o thread do aplicativo é bloqueado e nenhuma amostra de execução é registrada nele. Quando a amostragem é usada, a coleta de dados da TIP é a melhor maneira de entender quais atrasos de aplicativo ocorrem devido a chamadas síncronas para uma camada de dados.

A instrumentação usada pela TIP não captura pilhas de chamadas ao coletar dados de tempo. Se você estiver criando perfil de um aplicativo em camadas e não estiver totalmente familiarizado com o código, poderá ter dificuldade para determinar com precisão a origem das chamadas para a camada de dados. Os perfis de amostragem também podem ajudar a identificar em que local do código do aplicativo são executadas chamadas para essas interfaces do ADO.NET. Se o aplicativo fizer chamadas frequentes para interfaces do ADO.NET, provavelmente serão coletadas algumas amostras que mostram o tempo gasto em módulos do ADO.NET, inclusive System.Data.dll e System.Data.Linq.dll.

Ao examinar os dados de amostragem e compará-los com as medidas de interação de camada, lembre-se de que, enquanto um thread de aplicativo está bloqueado aguardando a conclusão de uma chamada síncrona de banco de dados, nenhum dado de amostragem do thread é coletado. As amostras acumuladas durante a execução excluem os atrasos fora do processo que a TIP mede explicitamente. No entanto, o que você pode esperar, é uma correlação aproximada entre as amostras de execução coletadas nos métodos do ADO.NET e o número de comandos do ADO.NET que a TIP observa e mede. Nesses casos, os perfis de amostragem podem ajudar você a navegar para o código-fonte onde se originam as chamadas do ADO.NET medidas e relatadas pela TIP.

Observe que, se um aplicativo tiver consultas SQL que retornem grandes resultsets que então são associados a um controle associado a dados em um formulário, você poderá encontrar um número significativo de amostras de execução no método DataBind do controle. Saber quais métodos DataBind aparecem no perfil de amostragem também pode ajudar você a navegar para o código-fonte onde se originam as chamadas do ADO.NET.

Perfis instrumentados

Quando os perfis instrumentados são coletados, os dados de tempo dos métodos registrados pela instrumentação já incluem o tempo gasto na espera pela conclusão de chamadas fora do processo no método. Os dados de tempo registrados em um perfil instrumentado são coletados por meio da medida do tempo na entrada e na saída de cada um dos métodos do aplicativo selecionados para instrumentação. Os dados de tempo dos métodos de um aplicativo cuja interface com uma camada de dados utiliza chamadas do ADO.NET incluem implicitamente o atraso na execução de quaisquer chamadas fora do processo.

Os dados de tempo coletados da TIP identificam e medem explicitamente os atrasos fora do processo separadamente. O atraso medido pela criação de perfil de interação da camada deve ser um subconjunto do tempo total gasto no método, conforme medido durante uma execução de criação de perfil instrumentado. Compreendendo isso, você deve conseguir fazer a correspondência entre os dados de tempo da criação de perfil de interação da camada com os dados de tempo coletados no nível de método em um perfil instrumentado, para localizar o método de origem da chamada para a camada de dados.

Se a instrumentação no nível de método for suficiente para permitir que você calcule a origem das chamadas do ADO.NET no aplicativo, o perfil instrumentado poderá ser usado sem hesitação. No entanto, os perfis instrumentados geralmente são mais invasivos do que os perfis de amostragem, incorrem em maior sobrecarga e tendem a gerar arquivos .vsp de coleta significativamente maiores. Além disso, se o aplicativo usar métodos que fazem várias chamadas para funções do ADO.NET, os dados coletados pela instrumentação só ajudarão você a navegar para o nível de método, não a diferenciar as várias chamadas do ADO.NET inseridas em um único método.

Mais dados, por favor

A criação de aplicativos com várias camadas é um padrão de design que promove a confiabilidade e a escalabilidade, mas não leva a desafios de monitoramento do desempenho quando os componentes do aplicativo são executados em computadores diferentes.

Uma simples exibição de um aplicativo de várias camadas que não abrange todas as camadas interconectadas não pode oferecer uma visão completa do seu desempenho. Como já foi visto, a TIP pode fornecer dados importantes de tempo que de outra forma seriam perdidos. Como sugere o exemplo deste artigo, esses dados de tempo podem ser aumentados com outros dados de desempenho das ferramentas padrão de administrador de banco de dados.

Mark Friedman é um arquiteto da equipe do Visual Studio Ultimate na Microsoft. Ele é o autor de dois livros sobre o desempenho do Windows e tem um blog periódico sobre problemas de desempenho em blogs.msdn.com/ddperf/.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Daryush Laqab e Chris Schmich