A maioria dos desenvolvedores considera que a otimização de desempenho é complexa e requer muita experiência e conhecimento. Bem, não se pode dizer que isso está completamente errado. Otimizar seu aplicativo para desempenho ideal não é uma tarefa fácil. No entanto, isso não significa que você não pode fazer nada se não tiver esse conhecimento. Aqui estão 11 dicas fáceis de seguir e práticas recomendadas para ajudá-lo a criar um aplicativo de bom desempenho.
A maioria das sugestões é para Java. Mas existem várias sugestões independentes da linguagem e podem ser aplicadas a todos os aplicativos e linguagens de programação. Antes de discutir técnicas de ajuste de desempenho especificamente para Java, vamos dar uma olhada nas dicas gerais.
1. Não otimize até saber que é necessário
Esta é provavelmente uma das dicas de ajuste de desempenho mais importantes. Você deve seguir as melhores práticas comuns e tentar implementar seus casos de uso com eficiência. No entanto, isso não significa que você deva substituir qualquer biblioteca padrão ou criar otimizações complexas antes de provar o necessário.
Na maioria dos casos, a otimização prematura não apenas levará muito tempo, mas também dificultará e manterá o código. Pior, essas otimizações geralmente não trazem benefícios, porque o que você gasta muito tempo otimizando é a parte não crítica do aplicativo.
Então, como você prova que precisa otimizar algo?
Primeiro, você precisa definir a rapidez com que o código do seu aplicativo é, por exemplo, especificando um tempo máximo de resposta para todas as chamadas da API ou especificando o número de registros a serem importados em um intervalo de tempo específico. Depois de fazer isso, você pode medir quais partes do aplicativo são lentas demais para melhorar. Então, vamos olhar para o segundo truque.
2. Use o analisador para encontrar o gargalo real
Depois de seguir a primeira sugestão e determinar que algumas partes do aplicativo precisam de melhoria, por onde começar?
Você pode resolver o problema de duas maneiras:
Confira seu código e comece com a parte que parece suspeita ou você acha que pode ser problemático.
Ou use o analisador e obtenha informações detalhadas sobre o comportamento e o desempenho de cada parte do código.
Espero não precisar explicar por que sempre devo seguir o segundo método.
É óbvio que uma abordagem baseada em analisador permite entender melhor o impacto de desempenho do seu código e permitir que você se concentre nas partes mais críticas. Se você usou um analisador, deve -se lembrar o quanto ficou surpreso ao descobrir quais partes do código tiveram problemas de desempenho. Para ser sincero, minha primeira adivinhação me levou à direção errada mais de uma vez.
3. Crie um conjunto de testes de desempenho para todo o aplicativo
Essa é outra dica universal que pode ajudar a evitar muitos problemas inesperados que geralmente ocorrem após a implantação de melhorias de desempenho na produção. Você sempre deve definir um conjunto de testes de desempenho que testa todo o aplicativo e executá -lo antes e depois das melhorias de desempenho.
Essas execuções de teste adicionais ajudarão você a identificar os efeitos colaterais funcionais e de desempenho da alteração e garantir que não sejam causados por mal a serem causados boas atualizações. Isso é especialmente importante se você trabalhar em componentes usados por várias partes diferentes do aplicativo, como bancos de dados ou caches.
4. Primeiro lide com o maior gargalo
Depois de criar um conjunto de testes e analisar o aplicativo usando o analisador, você pode listar uma série de problemas que precisam ser abordados para melhorar o desempenho. Isso é ótimo, mas ainda não responde à pergunta de onde você deve começar. Você pode se concentrar em soluções de ação rápida ou começar com as questões mais importantes.
Os esquemas de ação rápida podem ser atraentes no início, porque você pode mostrar rapidamente o primeiro resultado. Mas, às vezes, pode ser necessário convencer outros membros da equipe ou a gerência de que a análise de desempenho vale a pena - porque não há efeito no momento.
Mas, no geral, recomendo lidar com os problemas de desempenho mais importantes primeiro. Isso fornecerá as melhores melhorias de desempenho e pode não precisar mais resolver alguns desses problemas para atender aos requisitos de desempenho.
As dicas comuns de ajuste de desempenho terminam aqui. Vamos dar uma olhada em algumas dicas específicas de Java.
5. Use StringBuilder para conectar a String programaticamente
Existem muitas opções diferentes para conectar strings em Java. Por exemplo, você pode usar o simples + ou + =, bem como stringbuffer ou stringbuilder.
Então, qual método você deve escolher?
A resposta depende do código que conecta a string. Se você estiver adicionando novo conteúdo a uma string programaticamente, por exemplo, em um loop for, você deve usar o StringBuilder. É fácil de usar e oferece melhor desempenho do que o StringBuffer. Mas lembre-se de que, em comparação com o StringBuffer, o StringBuilder não é seguro para threads e pode não ser adequado para todos os casos de uso.
Você só precisa instanciar um novo StringBuilder e chamar o método Apênd para adicionar uma nova peça à string. Depois de adicionar todas as peças, você pode chamar o método ToString () para recuperar a sequência conectada.
O snippet de código a seguir mostra um exemplo simples. Durante cada iteração, esse loop converte I em uma corda e a adiciona ao StringBuilder SB junto com um espaço. Então, no final, esse código escreverá "Este é um teste0 1 2 3 4 5 6 7 8 9" no arquivo de log.
StringBuilder sb = new StringBuilder ("Este é um teste"); for (int i = 0; i <10; i ++) {sb.append (i); sb.append ("");} log.info (sb.toString ());Como você pode ver no snippet de código, você pode fornecer o primeiro elemento da string ao construtor. Isso criará um novo StringBuilder que contém a string fornecida e a capacidade de 16 caracteres extras. Quando você adiciona mais caracteres ao StringBuilder, a JVM aumenta dinamicamente o tamanho do StringBuilder.
Se você já sabe quantos caracteres sua string conterá, poderá fornecer esse número a diferentes construtores para instanciar um StringBuilder com capacidade definida. Isso melhora ainda mais a eficiência, pois não requer expansão dinâmica de sua capacidade.
6. Use + para concatenar a string em uma declaração
Quando você implementa seu primeiro aplicativo em Java, alguém pode ter lhe dito que você não deveria usar + para se conectar à String. Se você estiver concatenando strings na lógica do aplicativo, isso está correto. As strings são imutáveis e os resultados da concatenação de cada string são armazenados em um novo objeto String. Isso requer memória extra e desacelerará seu aplicativo, especialmente se você concatenar várias strings dentro de um loop.
Nesses casos, você deve seguir a dica 5 e usar o StringBuilder.
Mas se você apenas dividir a string em várias linhas para melhorar a legibilidade do seu código, isso é diferente.
Consulta q = em.createquery ("Selecione a.id, a.firstname, A.LastName"
+ “Do autor a”
+ “Onde a.id =: id”);
Nesses casos, você deve usar um simples + para concatenar sua string. O compilador Java otimiza isso e executa conexões no momento da compilação. Portanto, em tempo de execução, seu código usará apenas 1 string e nenhuma conexão é necessária.
7. Use primitivas o máximo possível
Outra maneira fácil e rápida de evitar qualquer sobrecarga e melhorar o desempenho do aplicativo é usar o tipo básico em vez de sua classe de wrapper. Portanto, é melhor usar o INT em vez de inteiro e dobrar em vez de dobrar. Isso permite que a JVM armazene valores na pilha, em vez da pilha para reduzir o consumo de memória e fazer um processamento mais eficiente.
8. Tente evitar Biginteger e BigDecimal
Como estamos discutindo tipos de dados, vamos dar uma rápida olhada no BigInteger e BigDecimal. Em particular, o último é popular por sua precisão. Mas há um preço.
Biginteger e BigDecimal requerem mais memória do que simples ou duplo e diminuem significativamente todos os cálculos. Portanto, se você precisar de precisão extra ou os números excederão o longo alcance, é melhor pensar duas vezes antes de fazê -lo. Esta é provavelmente a única maneira de mudar para resolver problemas de desempenho, especialmente ao implementar algoritmos matemáticos.
9. Primeiro verifique o nível de log atual
Essa sugestão deve ser óbvia, mas, infelizmente, muitos programadores a ignoram principalmente ao escrever código. Antes de criar uma mensagem de depuração, você deve sempre verificar o nível de log atual primeiro. Caso contrário, você poderá criar uma sequência de mensagens de log que será ignorada posteriormente.
Aqui estão dois exemplos negativos.
// Não faça thisLog.debug ("Usuário [" + nome de usuário + "] chamado Método x com [" + i + "]"); // ou thisLog.debug (String.format ("User [%s] chamado Método x com [%d]", nome de usuário, i));Nos dois casos, você executará todas as etapas necessárias para criar uma mensagem de log sem saber se a estrutura do log usará a mensagem de log. Portanto, é melhor verificar o nível de log atual antes de criar uma mensagem de depuração.
// faça thisif (log.isdebugenabled ()) {log.debug ("user [" + nome de usuário + "] chamado método x com [" + i + "]");}10. Use o Apache Commons StringUtils.Place em vez de String.Replace
De um modo geral, o método String.place funciona bem e é muito eficiente, especialmente ao usar o Java 9. No entanto, se o seu aplicativo exigir muitas operações de reposição e não for atualizado para a versão mais recente do Java, ainda é necessário encontrar alternativas mais rápidas e eficientes.
Há uma resposta alternativa ao método Stringutils.Place do Apache Commons. Como Lukas Eder descreveu em uma postagem recente do blog, o método Stringutils.Rplace é muito superior ao método String.Place do Java 8.
E requer apenas pequenas mudanças. Ou seja, adicione as dependências do Maven do projeto Apache Commons Lang ao aplicativo pom.xml e substitua todas as chamadas para o método String.place pelo método StringUtils.Rplace.
// substitua thistest.replace ("teste", "teste simples"); // por thisStringUtils.replace (teste, "teste", "teste simples");11. Recursos caros do cache, como conexões de banco de dados
O cache é uma solução popular para evitar a execução repetida de trechos de código caros ou comuns. A idéia geral é simples: é mais barato reutilizar esses recursos do que criar repetidamente novos recursos.
Um exemplo típico é uma conexão de banco de dados em um pool de cache. Novas conexões levam tempo para criar, o que pode ser evitado se você reutilizar as conexões existentes.
Você também pode encontrar outros exemplos na própria linguagem Java. Por exemplo, o método ValueOf dos valores de cache de classe inteiro entre -128 e 127. Você pode dizer que criar um novo número inteiro não é muito caro, mas porque é frequentemente usado, o cache os valores mais usados também pode fornecer benefícios de desempenho.
No entanto, quando você considera o cache, lembre -se de que as implementações de cache também podem incorrer em despesas gerais. Você precisa gastar memória extra para armazenar recursos reutilizáveis; portanto, pode ser necessário gerenciar caches para tornar os recursos acessíveis, além de excluir recursos desatualizados.
Portanto, antes de começar a armazenar em cache de recursos, verifique se a implementação do cache vale a pena, ou seja, você deve usá -los o suficiente.
Resumir
Como você pode ver, às vezes não é preciso muito trabalho para melhorar o desempenho do seu aplicativo. A maioria das sugestões deste artigo exige apenas um pouco de esforço para aplicá -las ao seu código.
Mas o mais importante são os truques que não estão relacionados à linguagem de programação é:
Não otimize o uso de analisadores para encontrar gargalos reais antes que você saiba que é necessário. Primeiro lide com os maiores gargalos.
O exposto acima é todo o conteúdo compartilhado neste artigo sobre as técnicas de ajuste de desempenho Java muito simples e fácil de entender. Espero que seja útil para todos. Amigos interessados podem continuar se referindo a este site:
Java implementa código detalhado para compartilhar funções da plataforma pública WeChat WeChat Moments
Análise comparativa de instâncias de desempenho de serialização nativa de Java e serialização de Kryo
Exploração sobre se a subclasse de programação Java pode reescrever o método estático da classe pai
Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!