Laravel Octane

Digital art by Anonymous

O que são Threads?

As threads são as unidades de execução de um processo. Um processo é como uma estrutura completa com seus próprios recursos e espaço de memória, enquanto as threads são linhas de execução dentro dele. Elas compartilham esses recursos e permitem que diferentes tarefas do mesmo processo ocorram ao mesmo tempo.

Processo Single Thread e Multi Thread

Um processo single thread possui apenas uma thread, o que significa que ele só tem uma linha de execução. Digamos que um script index.php precisa ser executado, o processo dele será single thread, e sua execução se dará linha por linha. Enquanto a linha 78 é executada, todas posteriores, do mesmo processo, estarão bloqueadas.

O processo em si, quando é single thread, possui apenas uma linha de execução, e sendo o código sequencial, a linha 79 e todas as outras posteriores estarão bloqueadas enquanto a 78 for executada.

No entanto, isso não significa que outros processos não possam ser executados enquanto outro está sendo. O que é bloqueado é a execução de tarefas ou linhas de um mesmo processo se ele for single thread. No PHP, por exemplo, cada requisição é um processo, podem ser enviadas 2 requisições para o mesmo servidor, o que seriam dois processos com diferentes alocações de espaço e memória, cada um single thread.

Um processo multi-thread possui mais de uma thread, ou seja, várias linhas de execução dentro do mesmo processo. Cada thread pode executar um pedaço do código de forma concorrente, podendo até rodar em núcleos diferentes da CPU, dependendo da disponibilidade.

Por exemplo, imagine um processo que precisa executar tarefas A, B, C e D. Em um processo single thread, essas tarefas seriam feitas uma de cada vez, bloqueando as posteriores até a conclusão da anterior. Em um processo multi-thread, as tarefas podem ser divididas entre threads diferentes e executadas ao mesmo tempo, reduzindo o tempo total de execução.

PHP e PHP-FPM

O interpretador do PHP é single-threaded para o processamento de uma requisição web típica. Isso significa que, quando um processo PHP está sendo executado, ele não divide a carga de trabalho em múltiplos threads internos para essa requisição específica. Ele processa a tarefa de forma sequencial, do início ao fim.

Por exemplo, se um script PHP precisa buscar dados de duas APIs diferentes, ele fará a primeira chamada e esperará pela resposta, e só depois fará a segunda chamada. Ele não consegue executar as duas chamadas simultaneamente.

O PHP-FPM (FastCGI Process Manager) contorna a limitação de thread único do interpretador PHP criando e gerenciando um "pool" de múltiplos processos PHP. Cada um desses processos do pool é chamado de "worker". 

Quando o servidor web recebe uma requisição destinada a um arquivo PHP, ele a encaminha para o PHP-FPM utilizando o protocolo FastCGI. O PHP-FPM, por sua vez, delega essa requisição a um de seus processos "worker" disponíveis, que executa o script PHP de forma single-threaded, do início ao fim. Após a execução, o "worker" retorna o resultado — seja HTML, JSON ou outro formato — ao servidor web, que o envia de volta ao cliente.

Em seguida, o "worker" volta a ficar livre para atender novas requisições. Esse modelo possibilita o processamento paralelo de múltiplas requisições, não por meio de threads dentro de um mesmo processo, mas sim através de diferentes processos trabalhando simultaneamente.

Swoole

O Swoole é uma extensão PHP escrita em C/C++ que transforma o PHP em um ambiente de programação de alto desempenho, assíncrono e orientado a eventos.

Em vez de iniciar e encerrar um processo PHP para cada requisição, o Swoole mantém um servidor HTTP rodando continuamente. Isso significa que o código da sua aplicação é carregado na memória apenas uma vez, e as requisições subsequentes são processadas por esse mesmo processo em memória, reduzindo drasticamente a latência.

O Swoole também utiliza um modelo de I/O não bloqueante e um event loop - como faz o Node.js. Isso permite que o PHP execute operações de I/O de forma assíncrona. Enquanto uma operação de I/O está pendente, o processo PHP pode continuar a processar outras requisições ou executar outras tarefas, em vez de ficar ocioso esperando. Quando a operação de I/O é concluída, um callback é acionado.

Com ele também é possível escrever requisições assíncronas. Em vez de usar callbacks aninhados, é possível usar "await" para pausar a execução de uma rotina até que uma operação seja concluída, sem bloquear o processo principal.

Laravel Octane

O Swoole, então, não é um framework PHP, mas uma extensão que fornece uma camada de abstração de rede e concorrência para o PHP. Por isso, ele permite que frameworks PHP existentes, como Laravel, aproveitem seus recursos para construir sistemas de alta performance, como APIs de tempo real, WebSockets, servidores de jogos e microsserviços.

Laravel Octane é um que otimiza o desempenho de aplicações Laravel ao executá-las em servidores de aplicação de alta performance, como Swoole. O Octane atua como uma ponte entre a sua aplicação Laravel e esses servidores, permitindo que a aplicação seja "bootada" (inicializada) uma única vez e permaneça em memória, processando requisições subsequentes em alta velocidade.

Os benefícios do Laravel Octane se traduzem em métricas de performance impressionantes. Um realizado pela Rivercrane comparou Laravel Octane com PHP-FPM utilizando o servidor NGINX. Os resultados mostraram que o Octane foi aproximadamente 5 vezes mais rápido, processando cerca de 42 requisições por segundo, enquanto o PHP-FPM processava cerca de 8 requisições por segundo.

Outro benchmark Laravel Octane com Laravel rodando sobre o Apache. O Octane processou 2.667 requisições em 10 segundos (266 requisições por segundo), enquanto o Apache processou 1.210 requisições (121 requisições por segundo).

Uma comparação entre Laravel Octane com Swoole e o framework AdonisJS que ambos conseguiram lidar com uma média de 20 requisições por segundo. O tempo médio de resposta foi de 6,4 ms para o Octane e 6 ms para o AdonisJS.