Sobre a questão do desempenho de versões antigas e novas de um nó

De tempos em tempos, os desenvolvedores que oferecem suporte a aplicativos de nós antigos têm dúvidas sobre a necessidade de transferir o aplicativo de versões antigas para novos nós. O principal argumento a favor de permanecer nos antigos é "Não uso novos recursos, mas a implementação deles certamente desacelerará o processamento como um todo". Além disso, a situação pode ser bastante complicada pela presença de dependências em bibliotecas que não são mais suportadas em novos nós, e uma alteração na versão de um nó se traduz automaticamente em um processamento significativo da arquitetura do aplicativo. Espero que meu artigo os ajude a decidir sobre esse assunto.

Antes de começar, lembro o princípio básico dos negócios de TI: FUNCIONA, NÃO TOQUE!

Se seu aplicativo funcionar da maneira que deveria, se ele lida totalmente com as tarefas e não houver necessidade urgente de seu processamento, é melhor deixar tudo como está. A reciclagem pode ser um processo muito doloroso e demorado. E, como resultado, você não obterá benefícios tangíveis, além de um senso de satisfação estética, e nesse momento seus negócios sofrerão.

Meu artigo é para quem ainda tem necessidade. Descreverei minha situação recente, falarei sobre as dificuldades encontradas para resolvê-la e apresentarei os resultados que finalmente recebi.

Estou desenvolvendo um sistema para coletar e processar logs de outros aplicativos. Cargas de trabalho estabelecidas - centenas de milhares de logs por minuto por componente. O sistema foi dimensionado bem horizontalmente, tinha uma arquitetura modular, trabalhou com sucesso por mais de um ano e lidou com suas funções como um todo. A versão usada do nó é 0.10

O que você está enfrentando?

Naturalmente, não falta de funcionalidade. Os novos recursos do es6 nem sequer foram considerados um argumento. Claro, eles tornam a vida um pouco melhor, mas nada mais. Para qualquer uma de nossas tarefas, a funcionalidade do nó antigo era suficiente. Os problemas surgiram no local mais inesperado à medida que a funcionalidade se tornou mais complexa.

Problema Um:

Um dos componentes com cargas de pico e consumo de memória abaixo de 5 GB repentinamente começou a desacelerar infernalmente. O problema não ocorreu toda vez, espontaneamente, geralmente perto do fim do pico. Se o aplicativo não cair no tempo limite, o desempenho se recuperará gradualmente dentro de meia hora ou uma hora. Reiniciar curado imediatamente.

Após o processo de "depuração profunda", verificou-se que todo o processo começa a desacelerar, inclusive as operações síncronas, motivo pelo qual foi concluído que o próprio coletor de lixo estava "piorando". O que fazer sobre isso não estava completamente claro. A única solução foi pesquisar o histórico de alterações em nosso código por vários meses e reverter funcionalidades importantes. Por outro lado, o problema não ocorreu com freqüência, nem todos os dias, e a reinicialização manual do sistema também parecia ser uma solução perfeitamente aceitável (manual significa um script baseado no sinal do detector de lista de pendências). Estávamos mais inclinados à segunda opção. E se não fosse o segundo problema, provavelmente seria implementado.

O segundo problema:

Outro de nossos componentes estava consumindo muita memória. Como esse componente era realmente um cache, sua “ganância” era em princípio explicável. Até o momento em que era necessário limitá-lo de cima para um volume estritamente especificado. E então o componente estava ganhando memória e não tinha pressa em entregá-lo. E mesmo trabalhando em velocidade quase ociosa. Ou seja, no momento do pico de carregamento, o gerenciador de memória do nó selecionou a memória máxima e, mesmo com uma margem, e a manteve até o final do século (reinicializando o componente, por exemplo). Mencionarei imediatamente que, naturalmente, a opção de vazamento foi examinada e verificada. Infelizmente, não houve vazamentos, e novamente estávamos em um beco sem saída.

Tentei perguntar em vários lugares na Internet como executar o gerenciamento de memória de um nó e como resolver nossa situação. Mas, em resposta, recebi muita negatividade em relação ao uso do nó 0,10. Em geral, foi essa negatividade que me levou à tarefa de mudar para as versões mais recentes do nó.

O que estava segurando?

1. Medo de perda de produtividade.

Aqueles que trabalharam em python lembram que a transição da linha 2.x para 3.x foi acompanhada por uma perda substancial de produtividade. Agora não sei como estão as coisas em python, talvez a situação tenha melhorado. Mas é bastante lógico esperar que, após adicionar todos esses novos recursos ao es6, o nó também possa afundar solidamente. Tentei pesquisar no Google alguns benchmarks para comparar novos nós com os antigos, não encontrei nada sensato.

2. Desempenho JSON.parse

Como trabalhamos com logs, o JSON.parse ocupa a maior parte do processador. Ao mesmo tempo, comparamos em diferentes versões do nó e obtivemos uma queda de desempenho de cerca de 30%. O nó 4.x foi comparado com 0.10 e 0.12.

De fato, esses motivos não foram decisivos, pois o processador não era um gargalo. Além disso, para essas tarefas, há escala horizontal.

3. Dependências do pacote

Mas isso foi uma pedra de tropeço. Nosso componente mais complexo central usou o pacote libmysqlclient, que funciona apenas no nó 0.10. Pior, suas chamadas síncronas. Ou seja, era impossível simplesmente mudar o driver mysql, substituindo uma chamada por outra, sem processar profundamente a arquitetura do componente, de processamento parcialmente síncrono para completamente assíncrono. Além disso, a parte mais difícil dessa tarefa não foi tanto o processamento em si, como justificar o gerenciamento de sua necessidade e mostrar o que exatamente isso daria ao projeto :)

O que deu?

Como resultado, ainda passamos do nó 0.10 para o último lts 8.11.x

1. Sem queda de desempenho. Pelo contrário, recebemos um aumento da ordem de 10 a 15%
2. Consumo de memória significativamente melhorado, cerca de 30-50%, dependendo do componente
3. Os problemas "insolúveis" mencionados acima foram resolvidos por eles mesmos
4. Finalmente tivemos a oportunidade de usar novos recursos do es6! Apesar do hábito, ainda não os usamos)))

Source: https://habr.com/ru/post/pt413673/


All Articles