BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Notícias Quatro estratégias para lidar com a contrapressão - Jay Phelps

Quatro estratégias para lidar com a contrapressão - Jay Phelps

Jay Phelps, membro da equipe principal do RxJS, palestrou no ReactiveConf 2019 explicando sobre o que é a contrapressão, quando acontece, e quais estratégias podem ser aplicadas para lidar com isso.

Para ilustrar o que é a contrapressão, Phelps deu o exemplo de um disco rígido que pode ler dados a 150 MB/s, mas pode gravar dados apenas a 100 MB/s. Isso deixa um déficit de leitura/gravação de 50 MB a cada segundo. Um arquivo de 6 GB é lido a toda velocidade em 40s e, se gravado imediatamente em outra seção do disco, deixará 2 GB do arquivo que foi lido porém não foi gravado imediatamente na memória, que pode ou não estar disponível. Esse é um problema típico da contrapressão, causado por um produtor (o processo de leitura) mais rápido que um consumidor (o processo de gravação).

Phelps definiu a contrapressão no contexto do software como uma resistência ou força que se opõe ao fluxo de dados desejado. No caso anterior, a resistência mencionada vem da estratégia mitigadora de ler dados mais rápido do que podem ser gravados, limitando (ou resistindo) a velocidade do produtor. Na maioria das bibliotecas de I/O (como Node.js streams), os mecanismos de contrapressão operam escondidos e o usuário da biblioteca não precisa se preocupar com isso.

A contrapressão também pode ocorrer no contexto da renderização da interface do usuário. O produtor pode ser o usuário que pressiona as teclas do teclado, o que nos levará a alguns cálculos que resultam em atualizações da interface do usuário. Quando o fluxo de atualizações da interface do usuário é mais lento que o fluxo de entradas do teclado, a contrapressão pode ser necessária. Isso geralmente é alcançado através da limitação ou desaceleração da entrada do teclado.

Como Phelps mencionou em um exemplo, atualizar o DOM mais rapidamente do que as atualizações de tela (60fps) é um desperdício. O método window.requestAnimationFrame pode ajudar a sincronizar as atualizações do DOM com o ciclo de atualização da tela.

Após os exemplos introdutórios, Phelps resumiu as quatro principais estratégias para lidar com a contrapressão. A primeira estratégia é aumentar os recursos para que o consumidor tenha a mesma, ou maior, velocidade que o produtor. A segunda estratégia, como ilustrado anteriormente, é controlar o produtor. Nessa estratégia, o consumidor decide a que velocidade o produtor envia os dados. Phelps forneceu um exemplo rápido no qual o consumidor extrai dados do produtor em vez de os enviar:

const source = connectToSource();

source.pull(response1 => {
  console.log(response1);

  // later...
 
  source,pull(response2 => {
    console.log(response2);
  });
});

A próxima estratégia, que foi usada no exemplo de disco rígido mencionado anteriormente, é o buffer, ou seja, a acumulação temporária de picos de dados recebidos. Essa estratégia de contrapressão sem perda pode, no entanto, levar a buffers ilimitados ou buffers que excedem a memória disponível.

Outra estratégia consiste em permitir a perda de dados descartando parte dos dados recebidos. As estratégias de amostragem / limitação / desaceleração ajustam o fluxo de dados recebidos para o consumidor, desconsiderando o excesso de dados.

Phelps posteriormente focou nas bibliotecas disponíveis que podem ajudar a implementar estratégias de contrapressão. As bibliotecas de fluxos baseadas em push (como Rxjs) podem ser usadas para implementar contrapressão com perda (como os métodos throttle, debounce, audit ou sample do RxJs). No entanto, os fluxos baseados em push não permitem o controle nativo do produtor, ou seja, a contrapressão sem perda requer um buffer potencialmente ilimitado. Fluxos baseados em pull (como o Node.js streams, Web Streams, iteradores assíncronos, como Repeater.js, IxJS, a versão baseada em pull do Rxjs) podem controlar ou pausar o produtor. Observe que os iteradores assíncronos são inerentemente mecanismos de push-pull, pois recebem uma solicitação de dados, que quando calculados, são enviados por push ao consumidor.

As soluções push e pull não são exclusivas e podem ser usadas juntas na mesma aplicação. Isso geralmente acontece no lado do servidor, mas também pode ser feito no lado do cliente. Por exemplo, o Rxjs pode ser usado, em algum contexto, em conjunto com iteradores para fornecer contrapressão sem perdas, sem recorrer a buffers ilimitados.

Qual estratégia adotar dependerá do problema em questão, por exemplo, se é possível, ou faz sentido, em um contexto específico, controlar o produtor. No caso de entradas do usuário, não é possível aumentar os recursos nem controlar o comportamento. Entretanto, as estratégias de contrapressão com perda geralmente ajudam. É benéfico para os desenvolvedores entenderem o conceito de contrapressão e as estratégias para solucioná-lo a fim de oferecer uma experiência ideal ao usuário.

O ReactiveConf é uma conferência anual voltada para desenvolvedores, com palestras abordando as mais recentes tecnologias e tendências no desenvolvimento de software. O ReactiveConf 2019 ocorreu de 30 de outubro a 1 de novembro de 2019 e está em sua quinta edição.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT