O segredo da otimização da versão 5.4 do PHP
Leia este artigo para saber mais sobre um otimização menos conhecida do PHP 5.4 e o que você precisa fazer para fazer com que o seu código PHP aproveite essa otimização para rodar mais rápido gastando menos memória.
O PHP 5.4 introduziu várias otimizações de desempenho. Uma delas não foi muito discutida na comunidade PHP, mas pode afetar o desempenho do seu código, dependendo da forma como você o escreve.
Leia este artigo para saber mais sobre essa otimização menos conhecida do PHP 5.4 e o que você precisa fazer para fazer com que o seu código PHP aproveite essa otimização para rodar mais rápido gastando menos memória.
O artigo também fala sobre uma especulação de que o PHP 6 e o Zend Engine 3 podem, no futuro, usar tipos de variáveis declaradas explicitamente e valores de retorno de função para gerar o código que faz os aplicativos PHP rodarem muito mais rápido.
Os prós e os contras de uma linguagem de programação dinâmica
Como todos sabemos, o PHP é uma linguagem dinâmica. A maioria dos desenvolvedores PHP aproveita essa característica, pois ela torna a programação mais descontraída e flexível.
Na prática, isso significa que você não precisa declarar antecipadamente os vários recursos que precisa usar, por exemplo, os nomes e os tipos de variáveis, como você tem que fazer em linguagens estáticas.
É claro que a programação dinâmica tem um preço. Se não souber antecipadamente os tipos de variáveis, não é possível fazer todos os tipos de otimizações que você poderia se os tipos de variáveis fossem corrigidos e conhecidos.
Variáveis de classe dinâmicas
No PHP, as classes podem ter um número variável de variáveis. Apesar de você poder declarar as variáveis que você sabe que serão necessárias, você também pode atribuir valores dinamicamente às novas variáveis que não foram previamente declaradas.
Isso significa que o mecanismo de execução do runtime do PHP precisa levar em conta essa possibilidade para gerenciar o acesso aos valores de variáveis de classe. Na prática, isso significa que, internamente, as propriedades variáveis de classe precisam ser armazenadas numa estrutura de dados dinâmica, que pode ser expandida conforme necessário.
A classe de otimização de acesso às variáveis do PHP 5.4
Rasmus Schulz (não é o criador do PHP, Rasmus Lerdorf) é um desenvolvedor dinamarquês que não muito tempo atrás levantou a preocupação de que o PHP poderia rodar mais rápido se ele fosse executado sobre um mecanismo compilador JIT.
Mais recentemente, ele levantou outra preocupação na lista interna de e-mails de discussão do PHP sobre a quantidade excessiva de memória usada na criação de muitos objetos de uma mesma classe. Sua alegação era que isso era devido ao fato de que para cada objeto PHP foi criada uma estrutura de dados dinâmica (tabela hash) para armazenar as propriedades de cada variável de classe.
Isso faz sentido se o PHP estiver esperando que a lista de variáveis de classe mude durante o tempo de vida de cada objeto. Mas se a lista de variáveis nunca, mudar será um desperdício de memória, pois diferentes objetos de uma mesma classe terão a mesma lista de variáveis, portanto, a classe poderia usar a mesma lista de propriedades, se ela tiver sido armazenada em uma estrutura de dados mais eficiente compartilhada por todos os objetos de uma mesma classe.
Foi quando o desenvolvedor Português Gustavo Lopes explicou que a partir do PHP 5.4 as propriedades dinâmicas de tabelas hash serão criadas somente se as variáveis forem adicionadas dinamicamente a objetos em tempo de execução.
Além disso, Tom Boutell concluiu na mesma thread de discussão que depois de executar uma atualização de script de teste com base no previsto inicialmente por Rasmus Schulz, usando apenas variáveis de classe pré-declaradas, o script não só usa muito menos memória, mas também funciona 20% mais rápido.
Até agora, deveria estar fácil para você entender que deve evitar o uso de variáveis de classe que não foram declaradas explicitamente na declaração da classe. Isso significa que você deve declarar todas as variáveis de classe, mesmo se não tiver definido um valor inicial.
Apesar de declarar explicitamente todas as variáveis de classe ser uma prática comum, alguns desenvolvedores não o fazem para todas as variáveis de classe que irão usar, especialmente se forem privados e não precisarem ter um valor inicial.
Os ganhos dessa otimização são apenas perceptíveis se você precisar criar muitos objetos da mesma classe em um script PHP. Se você criar apenas alguns objetos de uma classe, você pode não notar muita diferença.
Futuras otimizações de tipo de variável do PHP 6
Essa otimização do PHP 5.4 trabalha tornando mais eficiente a pesquisa de variáveis de classe pelo nome em tempo de execução, porque, quando uma classe é carregada, já sabemos quais são todas as suas variáveis, assumindo que nenhuma variável dinâmica será adicionada mais tarde.
Mais otimizações poderiam ser feitas se o mecanismo do PHP também conhecesse o tipo de variáveis e valores de funções de retorno a fundo. Isso é particularmente verdadeiro, não na versão atual do Zend Engine, porque ela trabalha ao interpretar os opcodes compilados do Zend, mas quando se usa um mecanismo compilador PHP JIT (Just In Time).
Pelo que sei, há pelo menos três compiladores JIT PHP: Facebook HipHop PHP, Phalanger e Quercus, que usariam o mecanismos de compilação do .NET e do Java JIT. Pode haver outros que eu não conheço, mas suponho que todos eles giram em torno dos mesmos conceitos.
Os compiladores JIT estão pelo menos a uma geração à frente da Zend Engine 2 usada na série PHP 5.x desde 2004. Os compiladores JIT podem fazer o PHP rodar mais rápido gerando e executando o código de máquina nativo otimizado para a CPU atual.
Atualmente, os mecanismos do compilador JIT tentam adivinhar a variável e os tipos de valor de retorno de funções a partir do contexto de código PHP para tornar o código de máquina gerado mais eficiente. Por exemplo, considere o seguinte código:
$ length = strlen ($ string);
strlen é uma função que sempre retorna um inteiro. Portanto, o compilador JIT pode declarar uma variável tipo integer, pois é certo que será sempre um inteiro. Esse tipo de adivinhação de valor é chamado de inferência de tipos.
Quando o tipo de uma variável não pode ser adivinhado com certeza, os compiladores JIT usam variáveis de um tipo chamado variant.
O uso de variáveis variant é muito menos eficiente porque as operações com essas variáveis podem exigir muitas conversões de tipo, pois não podemos assumir que tipo é o valor atual armazenado naquela variável. Isso significa que o código compilado JIT vai usar mais código de máquina nativo, mais memória, mais ciclos de CPU, portanto, menos desempenho.
Nos casos em que o compilador JIT não for capaz de adivinhar os tipos de variáveis do contexto, seria útil se o programador dissesse explicitamente qual é o tipo variável. Isso não só tornaria o código gerado mais eficiente, mas tornaria eventualmente a compilação JIT mais rápida, já que o compilador JIT não precisaria fazer suposições sobre o tipo de variável.
Declarações variáveis de classes digitadas poderiam ter esta aparência:
public integer $ l = 0;
Tradicionalmente, os desenvolvedores do core PHP têm sido relutantes em aceitar qualquer movimento no sentido de um tipo mais estrito de variável da linguagem PHP.
Mas a ideia que eu estou propondo aqui não é tornar o PHP uma linguagem fortemente tipada. A ideia é permitir que os desenvolvedores de PHP opcionalmente declarem expressamente o tipo, pelo menos de algumas variáveis, para que os compiladores JIT possam fazer um melhor trabalho gerando código de máquina nativo mais eficiente em menos tempo.
A declaração de variável e tipos de valores para PHP5.x/Zend Engine 2 dificilmente pode ser útil devido à natureza dinâmica da Zend Engine 2.
No entanto, para um eventual PHP 6 com base no Zend Engine 3 com suporte para compilação JIT, quaisquer dicas do tipo que o código PHP pode passar para o mecanismo JIT ajudarão a tornar o código PHP compilado muito mais eficiente.
Até onde eu sei, os planos para PHP 6 e Zend Engine 3 não são públicos, se é que eles existem. Mas não é nem cedo nem tarde para discutir o que eles serão. Eles podem muito bem resolver essa questão de eficiência, tendo em vista os benefícios de os compiladores JIT. Desconfio que a comunidade PHP vai falar sobre esses assuntos cada vez mais, porque parece ser o próximo passo lógico. Vamos ver.
Conclusões
Para ser preciso, a otimização do PHP 5.4 não era segredo. O fato é que ela não foi muito comentada entre os desenvolvedores externos do core do PHP.
Quanto às especulações sobre PHP 6 e Zend Engine 3 mencionadas acima, se elas já foram discutidas entre os desenvolvedores do core PHP, pelo menos para mim elas são realmente confidenciais, então minhas especulações são apenas palpites sobre o que eles podem vir a ser e, na minha provavelmente nem tão humilde opinião, deveriam ser.
De qualquer forma, uma vez que a otimização foi introduzida no PHP 5.4, essa é mais uma razão que pode convencê-lo a atualizar, caso você esteja se perguntando se realmente vale a pena. Em todo caso, você sempre deve avaliar cuidadosamente os prós e os contras da atualização para o PHP 5.4 antes de decidir fazê-la.
Então, o que você acha? Você está disposto a atualizar para os benefícios e outras otimizações do PHP 5.4 ou ainda tem preocupações que o impedem de atualizar?
E quanto às especulações sobre PHP 6 e Zend Engine 3? Você acha que o tipo de declaração de variáveis e funções seria algo que você usaria para tornar executar o PHP mais rápido?
***
Texto original disponível em http://www.phpclasses.org/blog/post/187-The-Secret-PHP-Optimization-of-version-54.html







