quinta-feira, 22 de julho de 2010

Não sofra depois, aperte o cinto logo no começo...

Com o passar do tempo em que você fica dentro de um único cliente, e quanto mais entende do negócio, sua importância aumenta exponencialmente dentro do projeto ou na integração desses projetos.

Por um lado essa situação é super interessante, pois é criado um elo de confiança, um relacionamento duradouro entre as empresas e, muito provavelmente, você melhore a efetividade do seu trabalho e dos resultados. Por outro lado, existe uma boa chance de que você acabe se tornando um ponto focal para solução de problemas e novas demandas, que vai impactar diretamente o gerenciamento do seu trabalho, pois o número de interrupções cresce demais e aquele trabalho técnico isolado fim a fim (que tanto gostamos de fazer), acaba sendo atrapalhado.


Particularmente eu estou vivendo essa situação que é muito gratificante e, como sempre, aprendendo demais com novos trabalhos, então resolvi compartilhar um aprendizado com vocês...


Estou trabalhando com o CRM 4.0 da Microsoft e carregando uma série de dados (oriundos de fontes diversas) utilizando como canal de entrada os web services publicados pelo produto. Recentemente codifiquei tudo o que precisava para importar uma entidade específica e larguei a rotina em background no servidor, fazendo a importação dos dados para essa entidade, que terá alguns milhões de registros.


Em um primeiro momento estávamos com uma média de 36.000 registros por hora, o que me dizia que em dez horas eu teria importado aproximadamente 360.000 registros. Como a rotina de inserção faz algumas chamadas de validação, para evitar - por exemplo - registros com um campo específico duplicado, essas rotinas ficariam mais pesadas com o tempo (pois aumentaria o volume de registros para validação dentro do CRM) e imaginei que o processamento efetivamente iria demorar mais do que um número X de dias estimados.


Com as inserções em andamento, o que eu previa aconteceu. Com o passar do tempo o número de registros importados por hora caiu, fazendo que a importação passasse a demorar mais tempo. Eu, com outras demandas (sempre urgentes e para ontem - vide parênteses abaixo) pensei: larga esse trem lá em background enquanto eu toco as outras tarefas, está ficando cada vez mais lento, mas me parece ser o comportamento normal.


Abre parênteses: ODEIO quando as pessoas que insistem em falar "ISSO É PARA ONTEM". Por acaso você têm uma máquina do tempo? Vai usar o delorean e viajar para o passado e fazer a entrega? Então animal da cauda, que tal parar de irritar as pessoas falando isso e discutir estratégias e novos prazos para você conseguir o que quer? Se era para ontem, ou não foi comunicado, planejado ou alguém cometeu um erro de estimativa, mas não importa, entenda o que aconteceu e foque na solução. Fecha parênteses.


Nesse meio tempo a importação ficou cada vez mais lenta, chegando a ficar quase 10 vezes mais devagar que a velocidade original. Achei bem estranho os números que estava vendo, mas sem tempo de analisar se o comportamento (e bem ou mal estava rodando), dei prioridade para outras tarefas, até esse fim de semana, onde o processo insistiu em sofrer com exceções de timeout do CRM.


Sem ter para onde correr, fui em busca da raiz o problema: VS debugger, profiler, tudo rodando direitinho e sabe o que eu descobri? Um índice fundamental para minha pesquisa no SQL Server não estava criado na tabela que representa a entidade! Pelo padrão de implementação que estamos utilizando, este índice já deveria ter sido criado, mas na falta dele as consultas acabavam em um lindo table scan.


Criado o índice para suportar a consulta, voltamos à taxa de importação que eu via no início do processamento (quando um table scan era baratinho, baratinho). Tudo resolvido, voltei para as outras atividades com essa experiência me cutucando (doida para chegar ao blog).


O interessante é que durante o fim de semana mandei um e-mail para um dos envolvidos no projeto, falando sobre o problema de timeout, e ontem fomos conversar quando ele disse: "Uma das ações que vou fazer é aumentar o timeout.". Sabe qual foi minha resposta: "Não, eu quero que você coloque o valor mais baixo possível para o timeout!" (foi curioso a cara de espanto do meu amigo).


Entendeu o motivo da minha requisição? Espero que sim...



A lição


Trabalhe (principalmente desenvolva) sempre com os menores limites possíveis, isto é, seja o mais restritivo possível nos tempos de resposta.


Passamos uma semana com uma importação rendendo pouco, muito pouco, mas como a coisa estava funcionando e rodando em background, eu priorizei outras atividades. Quando a tarefa realmente parou, eu precisei de menos de uma hora para corrigir o problema e voltar com uma importação dez vezes mais rápida. Acabei adiando o fim da importação em alguns dias por não ter gastado uma hora (OK, não tinha como adivinhar que seria somente uma horinha) para ver se a demora da importação era natural.


No que toca o CRM, se o timeout desde o início estivesse sido colocado bem baixo, o problema teria acontecido antes e com certeza hoje eu já estaria com todos os milhões de registros importados. Se pensarmos no desenvolvimento de novas soluções, é mais fácil você trabalhar com massas de dados e distribuições de recursos menores no desenvolvimento do que na produção. Aí talvez passe por aquele conhecido problema: "nossa, no desenvolvimento essa tarefa é tão rápida".


Então se no desenvolvimento você restringir bastante os seus timeouts (dos testes de unidade, acesso a dados - SQLConnection e SQLCommands -, chamadas a web services, etc.) provavelmente irá encontrar e resolver mais cedo alguns problemas que te assombrariam em produção. A partir de agora vou apertar o cinto logo no começo!



Melhor dificultar a coisa na sua máquina e resolver mais problemas, do que assistir de camarote quando, em produção, estiverem milhares de usuários acompanhando sua aplicação falhar... Pense nisso!


[]s
Luciano Caixeta Moreira - {Luti}
luciano.moreira@srnimbus.com.br
www.twitter.com/luticm
http://www.srnimbus.com.br/

4 comentários:

  1. muito bom Luti, parabéns.

    Realmente, a gente encontra muitos problemas simples de serem resolvidos, tanto na vida profissional quanto na pessoal, que acabam ficando de lado porque estamos "na correria"..

    ResponderExcluir
  2. Luti,

    Parabéns pelo post, acho que a expressão "A partir de agora vou apertar o cinto logo no começo!", cai como uma luva sobre esse problema.
    Acho que muito dos problemas que encontramos na empresa é exatamente o produto não ser testado em ambiente de homologação para depois ser colocado em ambiente de produção. A transação entre os ambientes é de suma importância para o desenvolvimento geral da prórpia ferramenta! Quando pensamos em um ambiente corporativo temos que pensar em CRESCIMENTO!, isso significa muito cautela na implementação, configuração da ferramenta que será colocada em produção!

    Parabéns por esse post muito bom mesmo!

    ResponderExcluir
  3. Pouts, perdi tempo lendo sobre obvio...

    ResponderExcluir
  4. Realmente são cuidados básicos que as vezes não temos.

    Oi Matheus, espero que você possa recuperar o tempo perdido com outros posts hahaha.

    Fiquei curioso com uma coisinha, qual é a configuração atual do timeout para os testes de unidade e dos comando/conexões dos projetos que desenvolvem?

    []s
    Luti

    ResponderExcluir