Http vs Sftp

June 20, 2009 on 12:22 pm | In performance, networking | 4 Comments

Upload do mesmo ficheiro binário não-comprimível, primeiro por HTTP e depois por SFTP.

HTTP vs SFTP

… como diria alguém conhecido, é por isso que “uma coisa é uma coisa e outra coisa é outra coisa”.

Thread-safe singleton?

March 11, 2009 on 12:18 pm | In performance, java | No Comments

Uma das piores coisas que se pode encontrar quando se pretende migrar uma aplicação single-threaded para multi-threaded é um Singleton que nunca o deveria ter sido, um daqueles que guarda informação de estado por todo o lado e que é usado em múltiplos sítios da aplicação ao longo de todo o ciclo de vida.

O que é se faz a uma coisa destas? A solução parece óbvia: “alteras o método instance() para devolver sempre um objecto novo”, efectivamente desfazendo o comportamento de singleton. Ok, funciona, mas e se o impacto em termos de performance for demasiado elevado? O que fazer quando se pretende manter o comportamento de singleton, mas ao nível do Thread, em vez de ser ao nível da JVM?

A resposta é substituir as variáveis existentes que guardam informação de estado por outras do tipo ThreadLocal<T>.

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

Ok, perfeito, não é?

Hmm… quase. Funciona bem se a criação dos threads for feita exclusivamente “antes” da primeira utilização da classe. Dessa forma cada thread inicializa a sua própria cópia uma só vez e trabalha com ela daí para a frente.

Mas e se forem necessários vários níveis de multi-threading, alguns dos quais “depois” da primeira utilização da classe? De acordo com a forma de funcionamento das variáveis ThreadLocal, cada thread filho teria uma instância nova, o que pode corresponder a esforço desnecessário e, dependendo dos casos, ter um impacto significativo no desempenho.

O nome diz tudo:  InheritableThreadLocal<T> é uma subclasse de ThreadLocal<T> que permite herdar a instância do thread pai se ela existir.

 This class extends ThreadLocal to provide inheritance of values from parent thread to child thread: when a child thread is created, the child receives initial values for all inheritable thread-local variables for which the parent has values. Normally the child’s values will be identical to the parent’s; however, the child’s value can be made an arbitrary function of the parent’s by overriding the childValue method in this class.

Agora sim, perfeito. :-)

JDBC e Reverse DNS Lookups

March 9, 2009 on 6:53 pm | In performance, java, windows, networking | No Comments

Se alguma vez ouvirem alguém queixar-se que uma aplicação Java client/server que funciona exclusivamente em rede local fica extraordinariamente lenta cada vez que o acesso à Internet cai, lembrem-se deste post.

Com uma descrição destas a primeira coisa que me ocorre é DNS. Como a aplicação não deixa de funcionar, fica simplesmente mais lenta, provavelmente o problema estará numa resolução inversa de DNS, que são frequentemente feitas pelas aplicações / middleware apenas para efeitos de logging.

Para não restarem dúvidas que o problema se relacionava com DNS, o servidor em causa tinha a configuração de DNS a apontar para o servidores do ISP, que obviamente ficam inacessíveis cada vez que se perde o acesso à Internet.

Comecei por procurar na aplicação, mas não encontrei nada que justificasse um lookup inverso de DNS. No tomcat encontrei um parâmetro que parecia promissor:

enableLookups - Set to true if you want calls to request.getRemoteHost() to perform DNS lookups in order to return the actual host name of the remote client. Set to false to skip the DNS lookup and return the IP address in String form instead (thereby improving performance). By default, DNS lookups are enabled.

Mas mesmo depois de desactivar o problema persistia. Descendo ainda mais na stack aplicacional descobri este bug no Java, já antiguinho, mas ainda aplicável à versão que estava a ser usada:

There is a call to InetSocketAddress.getHostName() in the ProxySelector code. This will trigger a reverse lookup when the hostname is not already known. If DNS is not configured correctly on the machine, this will generate a long timeout.

Foi este post na mailling list do Postgres que me conduziu ao bug em si e a descrição que fazem do problema é mais fácil de entender (e mais assustadora):

I can confirm that this is an issue in JDK 1.5 (a/k/a Java5) in Windows.  This is not the fault of postgres, but like others have suggested, it is with reverse DNS lookup.  It affects all TCP connections.
If you connect to an IP address it attempts to look up the name, resulting in these delays.

Se actualizar a versão de Java não for uma hipótese viável (como não era no meu caso), e se a resolução inversa ocorrer sempre para o mesmo endereço IP ou conjunto restrito de endereços, a solução pode ser mesmo adicioná-los ao ficheiro de hosts (C:\windows\system32\drivers\etc\hosts ou /etc/hosts).

Pelo caminho ainda descobri uma forma fácil de ver o conteúdo da cache de DNS num sistema windows:

ipconfig /displaydns

Se ficaram curiosos sobre como fazer a mesma coisa em Linux, a resposta não é fácil. Sem software adicional o kernel Linux não inclui uma cache de DNS, cada pedido é um pedido. Existe o nscd (Name Server Cache Daemon) que é bastante comum mas não vem pré-instalado em todas as distribuições (por exemplo não vinha no último Debian que instalei).

Java Profilling - TPTP

September 3, 2008 on 4:45 pm | In performance, java, open-source | No Comments

Cada vez mais me convenço que, logo a seguir a um debugger, uma ferramenta de profiling é das mais importantes para quem desenvolve software.A minha mais recente descoberta é precisamente um profiler para aplicações Java desenvolvidas em (e/ou para) Eclipse. Chama-se TPTP, que é acrónimo para Testing and Performance Tools Platform, e foi um bocadinho difícil de pôr a funcionar em Vista por causa do UAC, mas valeu bem o esforço.Esta ferramenta permite analisar com muito detalhe a utilização de CPU. Dá para fazer drill-down por package, classe e método; ver tempos gastos em cada nível da call stack, ou acumulados daí para baixo; e até desenhar gráficos de chamadas e dependências (que me parecem pouco úteis para projectos já com alguma dimensão, mas enfim).Não explorei muito as capacidades de Memory Analysis, porque não era o mais relevante para o projecto em causa, mas também estão lá. Só a performance de rede é que não está contemplada nesta plataforma, mas para isso existem o JMeter (se for HTTP) e o Wireshark (em todos os outros casos), que fazem muito bem o seu trabalho. 

© procself. Este blog está alojado no FEUP Blogs. Crie também o seu blog.
Subscreva os Artigos (RSS) e os Comentários (RSS) do procself.