Fibers - PHP

Fibers é um novo recurso do PHP 8.1 que traz simultaneidade leve e controlada ao PHP.

Provavelmente voce já leu essa frase em algum sitio, e assim como eu, voce não entendeu nada. Mas afinal, o que são Fibers? O que elas trazem de novo para o nosso codigo? Mais importante: Como isso vai agregar valor para o meu projeto?

Calma jovem mestre, neste artigo vamos tentar responder a essas duvidas.

Mas antes de tudo, precisamos de esclarecer que Fibers não é algo que o PHP inventou, outras linguagens tem essa implementação.

Vamos começar por entender o que são Fibers.

O que são Fibers?

Não tem como falar de Fibers sem falar de Threads(Não vamos explicar a fundo o que é). Mas basicamente**:**

Threads
Threads são uma forma de um programa se dividir em duas ou mais tarrefas e executalas de modo simultaneo, em um processo temos um ou mais threads, essas threads no mesmo processo compartilham os mesmos recursos.

As fibras são semelhantes as Threads. Os threads são agendados pelo sistema operacional e não garantem quando e em que ponto os threads serão pausados ​​e retomados. Isso quer dizer que é o Scheduler do Kernel que vai fazer a troca de contexto.

As fibras são criadas, iniciadas, suspensas e finalizadas pelo próprio programa e isso permitem um controle preciso da execução do programa principal e da execução da fibra.

Com Fibers , o bloco de código dentro da Fiber pode ser suspenso, retornar quaisquer dados ao programa. Depois o programa pode retomar a execução da Fiber exatamente no ponto em que ela foi suspensa.

É importante que a Concorencia não significa simultânemento. A Fibra e o fluxo de execução principal não acontecem ao mesmo tempo. Cabe ao fluxo de execução principal iniciar uma Fibra, e quando ele inicia, a Fibra é executada exclusivamente. O thread principal não pode observar, encerrar ou suspender uma fibra enquanto a fibra está sendo executada. A fibra pode suspender-se e não pode retomar por si só – o thread principal deve retomar a fibra.

Repare nas suspensões e no retorno da Fiber ao programa principal.

Vamos ilustrar da seguinte maneira:

Imagina que estás a fazer malabarismos com várias bolas ao mesmo tempo. Cada bola representa uma tarefa que tens de fazer, como desenhar algo bonito ou calcular números. Quando decides parar de fazer malabarismos com uma bola e pegar noutra, estás a trocar de tarefa.

Agora, pensa nos fibers como malabarismos, mas com um truque especial. Cada malabarismo (ou fiber) pode ser interrompido e depois retomado exatamente de onde parou. É como se pudesses pausar um malabarismo, fazer outra coisa por um bocado e depois voltar a ele sem deixar cair nenhuma bola.

Em PHP, os fibers são uma maneira de fazer isso mesmo. Eles permitem que o código pare e retome a execução, o que pode ser útil quando estás a lidar com várias tarefas ao mesmo tempo, como quando o computador está a realizar várias coisas ao mesmo tempo, mas de uma forma organizada.

Como as Fibers vão agregar valor ao meu projeto PHP?

Isso foi abordado na RFC que introduziu as Fibers no PHP8.1.

As fibras são um recurso avançado que a maioria dos usuários não usará diretamente. Este recurso é direcionado principalmente a autores de library e framework para fornecer um loop de eventos e uma API de programação assíncrona . As fibras permitem integrar perfeitamente a execução de código assíncrono ao código síncrono em qualquer ponto, sem a necessidade de modificar a pilha de chamadas do aplicativo ou adicionar código padrão.

Não se espera que a API Fiber seja usada diretamente no código em nível de aplicativo. As fibras fornecem uma API básica de controle de fluxo de baixo nível para criar abstrações de nível superior que são então usadas no código do aplicativo.

FFIé um exemplo de um recurso adicionado recentemente ao PHP que a maioria dos usuários pode não usar diretamente, mas pode se beneficiar muito nas bibliotecas que usam.

Mas isso não impede voce de usar no seu codigo, ou de criar uma Lib que resolva um problema usando Fibers.

Já falamos de muita teoria, vamos para um pouco de codigo.


Show me the code

PHP Fibers são implementadas em torno de uma nova classe chamada \Fiber .

Na documentação encontramos o seguinte exemplo:

<?php
$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('tilson');
    echo "Value used to resume fiber: ", $value, PHP_EOL;
});

$value = $fiber->start();

echo "Value from fiber suspending: ", $value, PHP_EOL;

$fiber->resume('test');
?>

Com a seguinte saida:

Value from fiber suspending: tilson
Value used to resume fiber: test

Vamos analisar:

1 - Criação da Fibra:

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('tilson');
    echo "Value used to resume fiber: ", $value, PHP_EOL;
});
  • Aqui, uma nova instância de Fiber é criada, como parametro ela recebe uma função anônima (closure). Essa função representa o código que vai ser executado quando a nossa fiber for chamada.

  • Dentro da nossa closure passada como parametro, temos $value = Fiber::suspend('tilson'); . O método só deve ser chamado de dentro da fibra.

    Quando Fiber::suspend()é chamado, o Fiber é pausado nessa expressão. As variáveis ​​locais, ponteiros de array, etc. não são apagados até que o próprio objeto Fiber seja removido da memória.

2 - Inicio da Fibra:

$value = $fiber->start();
  • O método start() é o gatilho, é que inicia a execução. O código dentro da função anônima é executado até encontrar a chamada para Fiber::suspend('fiber'). Neste ponto, a execução é pausada, e o valor 'tilson' é retornado e armazenado na variável $value.

3 - Inicio da Fibra:

echo "Value from fiber suspending: ", $value, PHP_EOL;
  • Aqui, o código principal (fora da fibra) imprime o valor que foi retornado quando a fibra foi suspensa. No exemplo, imprime "Value from fiber suspending: tilson".

4 - Retomada da Fibra:

$fiber->resume('test');
  • O método resume('test') é chamado na fibra, retomando a execução do código após a última chamada de Fiber::suspend(). O valor 'test' é passado para a variável $value dentro da fibra, substituindo o valor anterior.

5 - Impressão do Valor Atualizado:

  • Dentro da fibra, a execução continua a partir do ponto de suspensão, e o valor atualizado é impresso:
echo "Value used to resume fiber: ", $value, PHP_EOL;
  • No exemplo, isso imprimirá "Value used to resume fiber: test".

Resumindo, o código cria uma fibra, inicia sua execução, pausa a execução para obter um valor, imprime esse valor, retoma a execução da fibra com um novo valor e imprime esse novo valor.


Exemplo real

Um exemplo simples de echo provavelmente não mostra as vantagens de uma fibra porque ela não retorna nem passa nenhum valor. Vamos usar Fibers, em um programa simples que copia uma lista de arquivos para um destino pode ficar mais pratico.

<?php

function writeToLog(string $message): void {
    echo $message . "\n";
}
$files = [
    'src/01.jpg' => 'dest/01_copy.jpg',
    'src/02.jpg' => 'dest/02_copy.jpg',
    'src/03.jpg' => 'dest/03_copy.jpg',
];

$fiber = new Fiber(function(array $files): void {
    foreach($files as $source => $destination) {
        copy($source, $destination);
        Fiber::suspend([$source, $destination]);
    }
});

// Pass the files list into Fiber.
$copied = $fiber->start($files);
$copied_count = 1;
$total_count  = count($files);

while(!$fiber->isTerminated()) {
    $percentage = round($copied_count / $total_count, 2) * 100;
    writeToLog("[{$percentage}%]: Copied '{$copied[0]}' to '{$copied[1]}'");
    $copied = $fiber->resume();
    ++$copied_count;
}

writeToLog('Completed');

A operação real de cópia de arquivo é tratada dentro da Fiber, e o retorno de chamada do Fiber aceita apenas uma lista de arquivos para copiar e seu destino correspondente.

Depois que um arquivo é copiado, o Fiber o suspende e retorna os nomes de origem e destino ao chamador. O chamador atualiza o progresso e registra informações sobre o arquivo que acabou de ser copiado.

Usando um loop while, a fibra é reiniciada até terminar. Com o uso do Fiber, o retorno de chamada permanece enxuto porque não precisa lidar com outras operações, como atualizar o progresso.


Conclusão

Por hoje é tudo, espero que tenha te ajudado a entender um pouco sobre as Fibers no universo PHP, se gostou considere em assinar a minha Newsletter, assim sempre que sair algo novo desta serie de assuntos profundos no PHP, seras notificado.

Ate a proxima, valeu!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Did you find this article valuable?

Support Tilson Mateus by becoming a sponsor. Any amount is appreciated!