
Neste artigo, quero falar de uma forma popular-científica sobre como otimizar o tempo de resposta em plataformas de negociação de bolsas e bancos (HFT). Para referência, estamos falando de tempos de centenas de nanossegundos a centenas de microssegundos. Para a maioria das outras aplicações, muitos dos métodos de otimização abaixo são irrelevantes, simplesmente porque não existem requisitos rigorosos.
Normalmente, consideramos o desempenho em unidades de largura de banda. Por exemplo, no Gigaflops. A tarefa de otimização nesses casos é reduzida para executar o número máximo de cálculos por unidade de tempo ou resolver o problema no tempo mínimo. O design do processador foi projetado principalmente para atingir o número máximo de cálculos por unidade de tempo e técnicas de otimização padrão para o mesmo.
No entanto, existem aplicativos em que o tempo de resposta é mais importante, por exemplo, plataformas de negociação em comércio de computadores (HFT), mecanismos de pesquisa, robótica e telecomunicações. Tempo de resposta é o tempo de execução de uma operação "única" desse tipo, por exemplo, desde o recebimento de um pacote com cotações atuais da central até o envio do pedido para a operação de central. De fato, o tempo de resposta e a taxa de transferência (o número de operações desse tipo por unidade de tempo) estão intimamente relacionados, mas a diferença é fundamental. Muitas vezes, é possível aumentar a taxa de transferência simplesmente adicionando hardware (mais servidores), mas melhorar o tempo de resposta dessa maneira é problemático (exceto em casos de picos de carga).
Várias excelentes técnicas são usadas para otimizar o tempo de resposta. Alguns melhoram o tempo de resposta e a produtividade ao mesmo tempo, outros melhoram um às custas do outro. Por exemplo, para melhorar a taxa de transferência, o buffer é típico para processar uma matriz de pacotes por vez. Obviamente, para o tempo de resposta a um único pacote, essa abordagem é prejudicial.
Nas plataformas de negociação, a estabilidade do tempo de resposta também é muito importante. A maioria dos ganhos e perdas ocorre durante movimentos bruscos dos mercados, acompanhados por atividade anormalmente alta. A plataforma deve suportar tais cargas. Qualquer plugue pode causar perdas tangíveis.
Em geral, essa otimização de tempo de resposta de baixo nível é um tópico complexo que requer um bom entendimento da pilha de rede, o núcleo do sistema operacional, o desempenho do processador e da plataforma e a sincronização eficiente do encadeamento. Minha tarefa é explicar todas essas coisas complexas com um exemplo simples e compreensível.
Trabalho de escritório
Vamos usar a seguinte analogia. Imagine um grupo de pessoas trabalhando em um escritório. As comunicações ocorrem através da troca de mensagens em papel (cartas). Cada carta contém o destinatário, remetente e tarefa. As cartas são colocadas em determinadas mesas do escritório. Existem funcionários cuja tarefa é receber cartas do mundo exterior e colocá-las em mesas. Outros pegam cartas nas mesas e as transmitem aos tomadores de decisão. Cada tomador de decisão trabalha apenas com um certo tipo de letras (ou tarefas).
O tomador de decisão lê as cartas destinadas a ele e decide se essa tarefa será concluída, adiada ou ignorada. As tarefas para execução são empilhadas em uma tabela separada. Trabalhadores especiais pegam cartas nesta tabela e distribuem aos artistas. Algumas cartas devem ser respondidas fora do escritório, por exemplo, enviar confirmação ao remetente externo.
Para estar mais perto da realidade, vamos complicar um pouco mais as condições. Por exemplo, um escritório é uma rede complexa de salas e corredores, e diferentes tipos de trabalhadores só podem ir a determinados lugares onde têm acesso. Como dizem os matemáticos, sem perda de generalidade, suponha que nosso escritório, em condições normais, processe 200 mensagens por dia com um tempo médio de processamento de mensagens de 5 minutos.
Portanto, nossa tarefa é minimizar o tempo de processamento de mensagens. Nesse caso, é desejável que o tempo máximo de processamento não exceda a média mais do que, digamos, duas vezes. Ou seja, rajadas de atividade devem ser efetivamente tratadas.
Então, por onde começamos? A maneira mais fácil de contratar mais funcionários é processar mais mensagens. É bom procurar trabalhadores rápidos, pois o tempo de processamento será reduzido. Digamos que contratamos Usain Bolt e os outros finalistas olímpicos. Talvez o tempo de processamento tenha diminuído para 2 minutos. Mas é óbvio que não há para onde avançar mais nessa direção. Ninguém corre mais rápido. O limite é atingido. Comparando essas abordagens com um computador, a contratação de pessoas está comprando hardware adicional (servidores, processadores, núcleos) para aumentar o número de threads de execução. A contratação de atletas é semelhante à compra do ferro mais rápido (frequência máxima em primeiro lugar).
Talvez o layout do nosso escritório não seja o ideal. Deve haver espaço suficiente para os trabalhadores trabalharem com eficiência. Talvez expandir os corredores, caso contrário as pessoas terão que ceder uma à outra, perdendo um tempo precioso? Vamos expandir. Vamos também aumentar levemente as salas para que as pessoas não se amontoem ao se aproximar das mesas. É como comprar um servidor com mais núcleos, mais memória e largura de banda de E / S.
Além disso, podemos mudar para o serviço expresso, em vez de correio normal, para trocar mensagens com o mundo exterior. Em termos de computador, isso é semelhante à seleção e otimização de equipamentos de rede e da pilha de rede do sistema operacional. Tudo isso é um custo adicional, mas assumimos que eles definitivamente serão recompensados.
Então, após as inovações, nosso tempo de processamento de mensagens caiu para, digamos, um minuto. Os trabalhadores também podem ser treinados para melhorar o processo de comunicação e execução. Talvez isso dê 15% com a motivação certa. Ele sabe que chegamos a 51 segundos. Isso é semelhante à otimização de software.
O próximo passo é tentar evitar colisões entre nossos trabalhadores velozes. O provável gargalo é a abordagem das tabelas. É aconselhável que os trabalhadores tenham acesso instantâneo e simultâneo às mesas de que precisam. Você pode classificar as mensagens nas tabelas ao fazer o layout (colocar em pastas separadas) para acelerar o acesso. As mensagens também podem ter prioridades diferentes. No programa, este é um análogo da sincronização de threads. Os fluxos devem ter acesso paralelo e máximo ilimitado aos dados. A correção de problemas de sincronização de encadeamentos geralmente oferece um grande aumento na taxa de transferência do sistema e ajuda a melhorar os tempos de resposta. No sentido de processar rajadas de atividade, geralmente é difícil superestimar a influência de um algoritmo de sincronização ideal.
Além disso, às vezes os trabalhadores se encontram na frente de uma porta fechada. Outros pequenos problemas dessa natureza podem causar transtornos e atrasos. É aconselhável cumprir as seguintes condições: o número de pessoas em um determinado edifício nunca excede sua capacidade, a velocidade dos trabalhadores é ilimitada, nenhuma ação é tomada que não esteja relacionada ao trabalho principal e ninguém de fora entra no processo de trabalho. Em termos de computador, isso significa que o número de threads nunca excede o número de núcleos disponíveis, a plataforma está configurada para máxima frequência / desempenho, os modos de economia são desativados, o modo Turbo é ativado e o núcleo do sistema operacional e outros aplicativos é isolado e (quase) não afeta a plataforma de negociação.
Agora é hora de considerar com mais cuidado as condições do escritório. As portas abrem facilmente? O chão está escorregando? É o mesmo que analisar interações com o sistema operacional. Se não houver nada a melhorar, tente evitar o uso de certas peças. Por exemplo, em vez de entregar cartas pelo escritório, por que não tentar jogá-las de janela em janela? Você diz desconfortável? Pode ser desconfortável, mas rápido. Isso é semelhante ao uso da abordagem de desvio do kernel na pilha de rede.
Em vez de usar a pilha de rede do sistema operacional, o desvio do kernel executa a pilha de rede no espaço do usuário. Isso ajuda a se livrar de cópias de dados desnecessárias entre o sistema e a pilha do usuário e o atraso na execução do fluxo de recebimento de mensagens. No desvio do kernel, o fluxo de recebimento geralmente espera ativamente. Ele não fica no bloqueio do sistema operacional, mas verifica continuamente a variável de bloqueio até que ela lhe permita executar.
De fato, se começamos a jogar mensagens pelas janelas, vamos fazê-lo com eficiência. A opção mais confiável é passar pela janela de mão em mão. Este princípio é usado no protocolo TCP. Esta não é a opção mais rápida. O UDP permite que você simplesmente solte uma mensagem sem reconhecimento. É mais rápido Ninguém é obrigado a esperar. Acha que esse é o limite? Não, você ainda pode aprender a jogar pela janela para que a letra caia diretamente na mesa e na pasta desejadas. Essa abordagem é chamada de acesso direto à memória remota (RDMA). Acho que reduzimos o tempo de processamento de segundos para 35.
Ou talvez construir um escritório do zero, em vez de adaptar o existente às nossas necessidades? Tal que fornece condições ideais de trabalho. Talvez isso melhore o tempo de resposta de segundos para 20, ou até menos. O design do próprio escritório é o uso de FPGA (Field Programmable Gate Array). FPGA é algo como um processador cujo hardware está programado para resolver um problema específico. Um processador comum é codificado para executar um conjunto específico de instruções em determinados tipos de dados e o encadeamento de execução (que não deve ser confundido com o encadeamento de aplicativo) também é corrigido. Diferentemente do processador, os FPGAs não são pré-programados para um conjunto de instruções, tipos de dados e fluxo de execução. Eles são programados para uma tarefa específica e, nesse estado, são capazes de executá-la apenas (até a reprogramação subsequente). Uma programação FPGA eficaz não é uma tarefa fácil. Fazer alterações no programa também pode exigir muito esforço. E embora o FPGA não implique na contratação de Usain Bolt (as frequências são muito menores que as do processador), mas o paralelismo ilimitado da execução das instruções permite obter tempos de processamento de mensagens mais baixos do que no processador.
Bem, em conclusão, vou recomendar ferramentas de análise de desempenho para software. O amplificador Intel VTuneTM e a tecnologia Intel Processor Trace ajudam a ver em detalhes onde e por que o tempo da CPU é desperdiçado.
Se você estiver interessado no tópico, pode ler meus artigos na Intel Developer Zone (em inglês), que também fornece dicas técnicas práticas para otimizar o tempo de resposta.
- https://software.intel.com/en-us/articles/optimizing-computer-applications-for-latency-part-1-configuring-the-hardware
- https://software.intel.com/en-us/articles/optimizing-computer-applications-for-latency-part-2-tuning-applications