Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de Usuários
»Células Acadêmicas«
intcontpiada : 118
O melhor teclado da microsoft
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
Faça um pequeno teste com 10 questões de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programação com nosso treinamento on-line de lógica de programação
.:.
Veja nosso calendário de treinamentos
Gostou da Página?
Então

para um amigo!
 







Pesquisa personalizada
Pesquisar Dicas:

 






Quer saber mais?
Não deixe escapar essa oportunidade!
A Búfalo Informática tem os cursos certos para você:
::Treinamento para Asp.Net::
::Treinamento para VB.Net ::

Testando a performance de aplicações com o Application Center Test



O Application Center é um servidor criado pela Microsoft para gerenciar grupos de servidores Web e COM+. É um excelente servidor, por sinal, realiza tarefas que facilitam muito a vida do administrador da aplicação.

Junto com o Visual Studio .NET encontramos uma pequena parte do application center, o application center Test, que pode ser utilizado para testar a performance de aplicações.

Vou neste artigo demonstrar o uso do application center test para testar aplicações ASP comuns, não aplicações ASP.NET. Isso apenas para começar e comprovarmos alguns antigos conceitos, nos próximos artigos mostrarei alguns testes com aplicações ASP.NET e comparações entre aplicações ASP.NET e ASP.

Bem, para começar, devemos ter uma aplicação ASP, veja uma :

<html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     on error resume next
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select * from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields("companyname") %></td><td><%=rs.fields("contactname")      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Como podem observar essa aplicação tem diversas características que normalmente se recomenda que não sejam utilizadas. Vamos salvar esse arquivo como appteste1.asp e testa-lo através do application center test.

Devemos abrir o application center test através do menu Visual Studio .NET Enterprise Features, em start, programs, Visual Studio .NET.

Inicialmente já vemos um projeto de exemplo, ActSamples. Nada nos impede de criarmos nossos testes nesse projeto, mas podemos criar também um projeto novo através de File->New Project. O projeto funciona basicamente como um agrupamento de testes.

Vamos criar um projeto chamado ASPTESTS. Feito isso, vamos clicar no item Tests e com o botão direito pedir para criarmos um novo teste. Imediatamente abre-se a janela "New Test Wizard". A primeira pergunta feita é se desejamos criar um teste vazio ou gravar um teste. A forma simples de fazermos é, claro, gravarmos um teste.

Em seguida nos é pedida uma confirmação da linguagem utilizada para o teste, vbscript no caso, e entramos na tela de gravação. Ao clicarmos no botão Start Recording, o Application center test abrirá para nós o internet explorer e registrará todas as chamadas que fizermos com ele. No nosso caso, chamaremos o endereço de nossa aplicação, http://localhost/appteste1.asp

Por fim, damos um nome ao nosso teste (testeASP) e concluimos o Wizard. Agora temos que configurar algumas características do teste. Como a página é realmente muito pequena e rápida, para podermos ter comparativos de performance vamos executar o teste com um total de 500 usuários acessando a página. Para especificarmos isso devemos entrar nas propriedades do teste e alterar o test duration, dizendo que desejamos executar o teste um número específico de vezes. Poderíamos alterar também o número de usuários simultâneos para testar o comportamento da máquina, mas não faremos isso por enquanto.

Por fim poderemos iniciar a execução do teste e poderemos acompanhar essa execução conforme ela ocorre.

Pelo resultado do teste observamos que essa página levou 8 segundos para receber 500 requisições (isso testando em meu notebook). Pelo testresults podemos ver também que o average requests per second (média de requisições por segundo) foi de 62.50 (62.50 * 8=500)

Vamos começar a fazer alterações na página e ver o impacto que teremos em termos de performance. Vamos começar tirando o on error resume next :

<html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select * from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields("companyname") %></td><td><%=rs.fields("contactname")      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>


Com apenas 500 execuções o tempo de teste parece identico, mas se compararmos o average time to last byte (tempo médio até receber o último byte, em milisegundos) veremos que com o on error resume next foi de 11.15, enquanto que sem ele foi de 11.44. Não considero uma boa prática manter o on error resume next ligado em todo o código, mas perante esse teste é inegável que existe uma diferença de performance com a presença dele.

Vamos testar agora a declaração de variáveis e o option explicit :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select * from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields("companyname") %></td><td><%=rs.fields("contactname")      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Com este exemplo, o average time to last byte cai para 10.82, ou seja, realmente há um impacto na performance pela declaração de todas as variáveis e utilização do option explicit.

Vejamos agora com uma seleção mais específica de campos, ao invés do select * :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select companyname,contactname from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields("companyname") %></td><td><%=rs.fields("contactname")      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Com esta mudança o teste não dura mais 8 segundos, mas apenas 7 e o ATLB (Average time to last byte, vou abreviar) cai para 9.88, mais uma prova das boas práticas de programação sempre recomendadas.

Vamos ver o que acontece agora se ao invés de acessarmos os campos pelo nome, fizermos isso pelo seu número :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select companyname,contactname from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields(0) %></td><td><%=rs.fields(1)      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Temos agora um ATLB de 9.47. Usar números não é necessáriamente uma boa prática para manutenção de código, mas realmente é inegável que melhora a performance. Vamos tentar uma solução intermediária, com constantes :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs
     const companyname=0
     const contactname=1
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select companyname,contactname from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields(companyname) %></td><td><%=rs.fields(contactname)      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Com isso passamos a ter um ATLB de 9.61. Menos do que usando nomes, um pouquinho mais do que usando números, mas as vantagens em manutenção podem compensar. Vamos ver agora o que o response.buffer pode fazer por nós. Como estou testando isso no XP o buffer está ativado por default. Então vamos desativa-lo para fazer o teste :


     <% option explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs
     const companyname=0
     const contactname=1
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select companyname,contactname from customers",cn
     while not rs.eof %>
     <tr><td><%=rs.fields(companyname) %></td><td><%=rs.fields(contactname)      %></td></tr>
<% rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Neste caso o teste levou 1 minuto e 8 segundos para ser executado e o ATLB passou para 131.93. É inegável o ganho de performance proporcionado pelo buffer=true e isso deve ser lembrado especialmente por aqueles que ainda usam windows NT, que tem por default o buffer como false.

Vamos agora fazer um teste evitando a intercalação de código ASP com HTML :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs
     const companyname=0
     const contactname=1
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select companyname,contactname from customers",cn
     while not rs.eof
     response.write("<tr><td>")
     response.write(rs.fields(companyname))
     response.write("</td><td>")
     response.write(rs.fields(contactname))
     response.write("</td></tr>")
     rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Sem a intercalação o tempo passa para 7 segundos e o ATLB para 8.99, mais uma vez ganhamos performance em comparação com o 9.61 que tinhamos obtido anteriormente, provando que evitar a intercalação de código também traz ganho de performance.

Fazendo o mesmo teste com buffer=false obtive o resultado de 9 segundos e 14.32 de ATLB. De qualquer forma o buffer=false gera perda de performance, mas é interessante notar o gigantesco impacto de performance existente no buffer=false entre usar ou não intercalação de código ASP com HTML.

No nosso código estamos utilizando muito o objeto response dentro de um loop. Este objeto tem um certo peso em performance. Vamos ver o que aconteceria se utilizassemos uma variável string, fazendo concatenação e apenas um response.write ao final ;

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs,s
     const companyname=0
     const contactname=1
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial      Catalog=Northwind;Data Source=."
     rs.open "select companyname,contactname from customers",cn
     s=""
     index=1
     while not rs.eof
     response.write("<tr><td>")
     s=s & rs.fields(companyname)
     s=s & "</td><td>"
     s=s & rs.fields(contactname)
     s=s & "</td></tr>"
     rs.movenext
     wend 
     response.write(s)
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>

Neste caso o tempo volta para 8 segundos e o ATLB para 11.50. Isso porque como estamos usando buffer=true o processo de concatenação de strings, que envolve alocação de memória, consegue ser mais lento do que a utilização do objeto response. Vamos voltar então para a utilização do objeto response, mas um uma pequena diferença : Vamos reduzir nossa utilização do objeto recordset mantendo os fields em variáveis, veja :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs, compname,contname
     const companyname=0
     const contactname=1
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open ""
     rs.open "select companyname,contactname from customers",cn
     set compname=rs.fields(companyname)
     set contname=rs.fields(contname)
     while not rs.eof
     response.write("<tr><td>")
     response.write(compname.value)
     response.write("</td><td>")
     response.write(contname.value)
     response.write("</td></tr>")
     rs.movenext
     wend 
     rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>


Neste exemplo o ATLB passa para 8.95, uma diferença mínima comparando-se com o 8.99, melhor resultado que tinhamos até agora, mas é algum ganho.

Ainda estamos usando no nosso exemplo um objeto de conexão explicito. Vejamos a diferença de evitarmos isso :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs, compname,contname
     const companyname=0
     const contactname=1
     set rs=createobject("adodb.recordset")
     rs.open "select companyname,contactname from customers",""
     set compname=rs.fields(companyname)
     set contname=rs.fields(contname)
     while not rs.eof
     response.write("<tr><td>")
     response.write(compname.value)
     response.write("</td><td>")
     response.write(contname.value)
     response.write("</td></tr>")
     rs.movenext
     wend 
     rs.close
     set rs=nothing
     %>
     </table>
     </body>
     </html>


Nos meus testes o tempo subiu para algo entre 9.15/9.27 milisegundos. Assim sendo pode ser preferível definir a conexão explicitamente ao invés de usar apenas o recordset.

Vamos então voltar ao exemplo anterior e fazermos mais um teste : O que aconteceria se utilizassemos o método getstring do recordset ? Veja o código :

<% option      explicit %>
     <html>
     <body>
     <table with=100% border=1>
     <Tr><td>Empresa</td><td>Contato</td></tr>
     <% 
     dim cn,rs, s
     set cn=createobject("adodb.connection")
     set rs=createobject("adodb.recordset")
     cn.open "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial      Catalog=Northwind;Data Source=."
     rs.open "select companyname,contactname from customers",cn
     s="<tr><td>" & rs.getstring(2,,"</td><td>","</td></tr><tr><td>")      & "</td></tr>"
 response.write(s)
 rs.close
     cn.close
     set rs=nothing
     set cn=nothing
     %>
     </table>
     </body>
     </html>


Neste exemplo o tempo de execução baixa para 6 segundos e o ATLB para 7.85. Sem sombra de dúvida o melhor resultado obtido


Com estes exemplos mostramos como fazer uso do application center test que acompanha o Visual Studio .NET para testarmos aplicações Web e fizemos algumas comparações de performance entre várias formas de realizarmos as mesmas tarefas. Em artigos posteriores estaremos fazendo algumas comparações com aplicações ASP.NET.

Dennes Torres
MCSD,MCSE,MCDBA



� Búfalo Informática, Treinamento e Consultoria - Rua Álvaro Alvim, 37 Sala 920 - Cinelândia - Rio de Janeiro / RJ
Tel.: (21)2262-1368 (21) 9240-5134 (21) 9240-7281 e-Mail:
contato@bufaloinfo.com.br