O que há de novo no Node.js v0.12 – Otimizações de Performance

O longo ciclo de desenvolvimento da versão v0.12 (nove meses e continua aumentando, o maior até agora) deu à equipe principal de desenvolvimento e aos contribuídores uma ampla oportunidade de introduzir várias otimizações de performance. Esse artigo pretende cobrir as mais notáveis.

Suporte a Cork para streams de escrita.

Streams de escrita agora suportam um modo “corked”, semelhante às opções de socket TCP_CORKTCP_NOPUSH, descritas em man tcp.

Nesse modo corked, dados escritos no stream são enfileirados até que o stream seja desbloqueado novamente. Isso permite que o Node combine pequenas operações de escrita em operações de escrita maiores, resultando em menos chamadas de sistema e menos roundtrips no TCP.

O módulo http foi atualizado para utilizar esse modo corked de forma transparente ao enviar um pedaço de requisição ou um corpo de resposta. Se você verificar frequentemente a saída do strace(1), vai notar mais chamadas de sistema writev(2) e menos chamadas write(2).

Melhorias de performance TLS.

O módulo tls foi consideravelmente retrabalhado no Node.js v0.12.

Na versão do Node.js v0.10, o módulo tls trabalha sobre o módulo net, automaticamente encriptando e desencriptando o tráfego de rede. Essa camada de abstração é desejável do ponto de vista de engenharia, mas introduz um overhead – mais memória sendo movimentada, e muito mais chamadas dentro e fora da máquina virtual V8 que o necessário – e atrapalha as otimizações.

É por isso que no Node.js v0.12, o módulo tls foi completamente reescrito para usar diretamente alibuv. O módulo agora trabalha diretamente sobre o tráfego de rede, e desencripta o mesmo, sem passar por camadas intermediárias.

Testes não científicos usando uma cifra nula sugerem que o TLS é agora cerca de 10% mais rápido, e consome menos memória. (Importante notar que a redução do uso de memória se deve em parte ao retrabalho no gerenciador de memória, uma outra otimização do v0.12).

(E caso você esteja se perguntando, uma cifra nula é uma cifra que não encripta o payload. Isto é útil pra medir o overhead de protocolo e infraestrutura.)

A maioria das mudanças no módulo tls devem ser transparentes ao usuário final. A mais visível é que as conexões TLS agora derivam de tls.TLSSocket, ao invés de tls.CryptoStream.

Read more

O que há de novo na versão v0.12 do Node: Cluster de Balanceamento de Carga Round-Robin

Nota do editor: Bem vindo à primeira parte do que provavelmente será uma série de sete ou oito postagens no blog de autoria dos commiters do núcleo do Node, BenNoordhuis e Bert Belder, cobrindo os novos recursos que atualmente estão previsto para a versão v0.12 de Node. Neste primeiro post, Ben foca no novo algoritmo de clustering round-robin.

Resumo: módulo de cluster embutido do Node

Antigamente, uma limitação freqüentemente lamentada do Node era o seu modelo intrinsecamente single-threaded. Não importa quantos núcleos havia na máquina, o Node iria utilizar apenas um núcleo (com a ressalva de que algumas operações são descarregadas em um pool de threads. Para a maioria das aplicações, isso é apenas um pontinho considerando toda a quantidade de tempo da CPU, porém isso realmente não ajuda com uma melhor utilização do processamento disponível.)

É por isso que a versão v0.8 do Node viu a adição do novo módulo integrado: o “cluster”. O módulo de cluster permite configurar um processo mestre que atua como um supervisor e um ou mais processos que executam o trabalho real.

Um dos objetivos foi de tornar fácil a criação de servidores multi-processo fire and forget. Em um mundo perfeito, você deve ser capaz de pegar uma aplicação existente de processo único e gerar como achar melhor o maior número de processos worker, sem ter que mudar uma única linha de código na aplicação.

Claro que nada é tão fácil assim, mas o módulo de cluster fica simples para as aplicações que têm um pouco ou nenhum estado compartilhado, ou armazenam o estado compartilhado em um recurso externo como um banco de dados ou um serviço web. Transformar uma aplicação assim em uma aplicação clusterizada normalmente leva apenas algumas linhas de código:

A aplicação não precisa saber se está sendo executado em um ambiente clusterizado. Imagine se você fizer o app() parecido com:

Read more

O que há de novo na versão v0.12 do Node: Debug de aplicações clusterizadas com Node-Inspetor

Agora, a maioria de vocês já descobriram como usar o mais recente e melhorado node-inspetor(construído com ferramentas de desenvolvimento do Google Blink) para debugar aplicações Node. Mas que tal aplicações clusterizadas? Neste blog vamos apresentar o que é preciso ser feito para realizar essa façanha.

Debugar uma aplicação Node clusterizada não deixa de ser uma idiossincrasia, particularmente caso esteja executando a versão do Node v0.10. Mas, ele funciona bem o suficiente caso você entenda o que ocorre dentro dos bastidores. Agora, antes de embarcar nesta aventura de debug, você provavelmente deve se perguntar, “(i) posso executar minha aplicação não-clusterizada e debugá-la nesse modo ou (ii) é uma issue que estou tentando rastrear, vista somente ao executar minha aplicação numa configuração clusterizada?”

Se for o primeiro caso, certamente pode usar o node-inspetor para debugar a aplicação numa configuração clusterizada. Mas, isso envolve uma seqüência de várias etapas para funcionar:

  • execute a aplicação
  • execute o node-inspetor
  • abra uma nova aba no Chrome

Começando com o node-inspetor

Uma das maneiras mais fáceis para começar o debug com o node-inspector é instalar a ferramenta de linha de comando da StrongLoop, o strong-cli, que fará toda a configuração necessária.

Get started with node-inspector

Read more

O que há de novo no Node v0.12 – execute várias instâncias em um único processo

Um recurso que é bastante solicitado é a capacidade de incorporar o Node em outras aplicações, em especial de uma maneira que permita a integração com outros loops de evento e com suporte para múltiplos contextos de execução: ou seja, a capacidade de ter várias instâncias Node coexistindo pacificamente dentro do mesmo processo. Imagine uma aplicação node-webkit, onde cada janela executa sua própria instância de Node e que fique isolada de todas as outras janelas. Ou imagine o Node sendo incorporado em um telefone ou num switch de rede onde há a execução de lógica de roteamento para múltiplas conexões, mas em um único processo (o que não está muito longe).

GitHub veio até nós precisando desse tipo de funcionalidade para o Atom.io. É pedir demais, justamente porque o Node começou como – e ainda é – uma aplicação single-threaded (de uma única thread), construído em torno do conceito de um único loop de evento, e com centenas de variáveis globais que armazenam vários bits de estado.

Você pode imaginar como que o reajuste de thread-safe em cada base de código é uma tarefa altamente sujeita a erros e é por isso que nós não fizemos – ou melhor, ainda não está feito. Nós queríamos fazer essa mudança de uma forma acessível ao cliente e em passo incremental que iria ajudar toda a comunidade. Aliás, se você precisar de algumas mudanças no Node, mas está sem tempo para descobrir como fazer alterações, nós podemos lhe ajudar!

Introdução a contexto múltiplo

Em vez disso, fizemos com que isso seja possível no Node v0.12 para possibilitar o uso de múltiplos contextos de execução de dentro do mesmo loop de eventos. Mas não se preocupe: do ponto de vista do usuário, não há nenhuma mudança visível, tudo continua funcionando como era antes. Mas caso você seja um embedder ou um autor de complemento nativo add-on, continue a leitura!

O trabalho de “contexto múltiplo” que está no commit 756b622 é primeiramente uma limpeza de job: isso ocorre em todos os globals, eliminando aqueles que não precisam ser global de imediato e transformando os restantes em propriedades de contexto de execução. Isso não nos dá a segurança de thread ainda, mas já é um primeiro e importante passo.

A segunda parte está fazendo os internals do Node ter conhecimento da existência de múltiplos contextos de execução. Em toda parte, as runtime do C++ chama a máquina virtual V8, e é preciso ter certeza de que o primeiro contexto foi entrado corretamente. Um rápido exemplo:

Execução-sábia, é algo do tipo:

Entre as chamadas na VM, é possível mudar o contexto de execução. Portanto é essencial queconnect() lembre do contexto atual e que a chamada onconnect() restaure esse contexto. Se não fizer isso pode provocar alguns bugs que são realmente difíceis de rastrear.

Read more

Além da versão v0.12 do Node: reflexões sobre um roteiro para o futuro

A equipe StrongLoop recebeu uma grande quantidade de feedback da comunidade no ano passado e ultimamente nós (equipe StrongLoop) temos pensado muito sobre esses feedbacks. Nós perguntamos a nós mesmo “como que pode uma empresa, desenvolvedores individuais e membros de uma comunidade ser os contribuidores mais ativos do Node que consequentemente beneficia a todos? Desde desenvolvedores individuais a clientes de um ecossistema de fornecedores que oferece serviços e produtos ao redor do Node?”

O resultado é este post onde nós já colaboramos com colegas de trabalhos, tanto dentro quanto fora da StrongLoop, para tentar articular o que achamos que a StrongLoop pode fazer de mais útil para ajudar a comunidade a levar o Node para um outro nível.

É claro que não estamos falando do responsável do projeto ou da comunidade como um todo. Estamos sim colocando uma discursão em pauta, como membros da comunidade do Node, para que você possa entender melhor onde pretendemos concentrar os nossos esforços de desenvolvimento no futuro.

Um futuro governado por APIs e JavaScript

Como uma série de recursos do Node tem evoluído ao longo dos anos, e a comunidade tem crescido, o Node emergiu como a tecnologia preferida para o front-edge. Os casos de uso de umfront-edge incluem:

  • Aplicações web de página única (aplicações single-page)
  • Sensores e dispositivos embarcados
  • Aplicações que exigem recursos em tempo real
  • Servidores de API – que é a “cola” que une os dispositivos com o backends e os serviços

Achamos que os requisitos desses casos de uso irão naturalmente girar em torno dos desenvolvedores para a programação governada por APIs e JavaScript.

  • A capacidade de escrever aplicações isomórficas: com o JavaScript executando no navegador, no dispositivo e no servidor significa uma maior oportunidade não só para a reutilização de código, mas também para o reaproveitamento das habilidades dos desenvolvedores. Com o Node, cada desenvolvedor JavaScript tem o potencial para se tornar um desenvolvedor server-side. O JavaScript como full-stack continua ganhando popularidade como por exemplos as pilhas MEAN e BACN.
  • Suponha que às vezes os dispositivos estarão off-line: o Node pode ajudar a facilitar a sincronização de dados em dispositivos que nem sempre estará conectado a um back-end.
  • Dispositivos conversando com dispositivos: como nós estamos aproximando rapidamente de uma época onde haverá mais dispositivos e sensores trocando dados entre si do que a troca de dados iniciada por seres humano, os recursos de eventos do Node brilham ao ajudar a fazer coisas como conectar carros e possíveis dispositivos inteligente de automação residencial.
  • SDKs com recursos fully-featured: Facilita aos desenvolvedores que estão familiarizados com plataformas nativas como iOS e Android na integração de aplicações Node, sem exigir uma curva de aprendizagem.

O que se segue são as oportunidades e desafios que acreditamos que exista para desenvolvedores e organizações similares, interessadas em levar o Node para um próximo nível.

Read more