DEV Community

Leandro Henrique
Leandro Henrique

Posted on • Edited on

Benchmark PHP X Elixir

Introdução

Estou a 30 dias estudando Elixir, eu não tenho intenção nem de denegrir a imagem do Elixir que estou apaixonado e nem de enaltecer o PHP e minhas considerações sobre Elixir podem ser equivocadas aja visto que há muito ainda para eu aprender.

Em uma das aulas propostas pelo curso tinha a leitura de um arquivo de 300 mil linhas para gerar um relatório. Depois de gerado o relatório uma melhoria no relatório dividindo o arquivo em 3 e processando fazendo uso do concorrência.

Os resultados foi surpreendente ao fazer uso de concorrência, processando 3 arquivos ao mesmo tempo, foi aproximadamente 33% do tempo, mas aqui que começa ficar bom, eu pensei: E o PHP, quanto tempo ele levaria para fazer o mesmo processo?

Brincadeira começa aqui.

Bom para fazer comparação entre PHP e Elixir eu multipliquei as linhas fazendo o relatório ter 9 milhões de linhas.

E vou utilizar o time, para medir o início e o fim de cada resultado, não vou postar vários resultados, você poderá testar ao final cada um quantas vezes quiser e ver o resultado por você mesmo.

Versões utilizadas

Elixir 1.12-dev e 1.11.3
PHP 8.0 e 7.4

Elixir - Arquivo único

time -vvv mix run init-complete.exs

User time (seconds): 24.19
Percent of CPU this job got: 124%

Memória utilizada em todos os testes do Elixir variou de 28 a 33 megas. Usando :erlang.memory(:total) para saber a quantidade de memória utilizada.

PHP - Arquivo único teste 1 - com debug

O primeiro teste foi similar ao do Elixir com a diferença de utilizar 3,7 gigas de memória, só que eu tentei executar o mesmo no Mac que só tem 8 Gigas de memória e não executou, somente no meu PC e no meu Notebook que tem 64GB de Memória ram, porém em outro teste com arquivo menor o de 300 linhas no Mac o tempo ganhava do Elixir. Eu fiquei intrigado, descobri o motivo: no Mac o Debug não estava ativado.
Por isso não coloco o resultado do primeiro teste do php, acho irrelevante, mas acho relevante mencionar o debug ligado que pode alterar muito o resultado.

PHP - Arquivo único teste 2 - sem debug

time -vvv php reports/report.php

User time (seconds): 8.51
Percent of CPU this job got: 99%
Memória Utilizada: 3,7 Gigas

Bom PHP ganha no tempo, no uso da CPU, mas perdeu de lavada no uso da memória. Foi então que meu amigo Bruno me lembrou da existência do yield no PHP que eu já tinha lido, mas nunca usei, fui procurar como usar e fiz um novo teste.

PHP - Arquivo único teste 3 - sem debug e com yield

time -vvv php reports/yield.php

User time (seconds): 6.13
Percent of CPU this job got: 99%

O uso da CPU continuou o mesmo,porém o tempo caiu quase 3 segundos, além que o uso de memória ganhou de lavada do Elixir neste caso, pois usou apenas 2 megas de memória, isso mesmo, você leu corretamente, 2 megas. Até no Mac eu consegui executar este teste, que antes não era possível pela capacidade de memória.

Então eu dividi os arquivos em 3 e fui fazer o teste com concorrência.

Elixir concorrência - 10 arquivos

time -vvv mix run init-many10.exs

User time (seconds): 41.69
Percent of CPU this job got: 903%

Tempo aumentou muito, e o uso do processador, achei que coloquei muitos arquivos, então dividi em 3 apenas e depois com 2 arquivos vou colocar o resultado só com 2 arquivos que achei mais relevante e de menor tempo.

Elixir concorrência - 2 arquivos

time -vvv mix run init-many2.exs (ops, usar o time para este teste pareceu injusto, visto que por algum motivo ele fica o dobro do tempo).

Então para este teste, executei via terminal:

iex -S mix
:timer.tc(fn -> ReportsGenerator.build_from_many(["outaa", "outab"]) end)
Enter fullscreen mode Exit fullscreen mode

10 segundos. Memória sempre se manteve aproximadamente a mesma.

Uso de CPU caiu relacionado a processar 10 arquivos ficando em 300%, o tempo caiu pela metade, embora ainda assim o php sem concorrência ganhou no tempo.

PHP concorrência

Eu não fiz o teste com concorrência em PHP, pois é necessário usar ferramenta como Swoole, além do tempo para refatorar o código de moda a usar coroutine.

Conclusão

Os testes não são conclusivos, porém o PHP se mostrou com desempenho melhor mesmo sem usar concorrência, mas devemos considerar que eu executei o Elixir em modo de desenvolvimento, se executar em modo produção os valores podem serem alterados consideravelmente devido a bibliotecas que não serão carregadas em produção assim como aconteceu ao desativar o debug do PHP, mas ainda não coloquei nada em produção da forma correta para poder ser mais justo com Elixir, então fica a seu cargo testar.

P.S.: PHP não usou o recurso de JIT, até achei que ele estava fazendo uso na versão 8.0, porém executei o teste utilizando a versão 7.4 que não tem JIT e o tempo foi o mesmo ou com tempo insignificante de diferença.

Seria bacana ver os mesmos teste em Go e Rust, eu gostaria muito de ver os resultados, alguém se habilita?

Se você quiser fazer seus próprios testes ou até mesmo colocar o PHP em concorrência, segue os scripts que utilizei: https://github.com/emtudo/reports_generator

Top comments (3)

Collapse
 
rhamorim profile image
Roberto Amorim

Será que tem algo a ver com o bug mencionado aqui: github.com/elixir-lang/elixir/issu... ?

Collapse
 
emtudo profile image
Leandro Henrique

Não me parece ser este problema, uma vez que é esperado como o José Valim diz sobre a função. Porém creio que o Elixir poderia entregar mais se tivesse em modo de produção.

Collapse
 
patryk profile image
Patryk Woziński

It would be great to read it in English :(