Criando Extensões para o PHP: Parte I – Introdução
Olá Leitores!
Hoje pretendo iniciar uma empreitada ao “submundo” do PHP, onde vamos explorar suas entranhas e tentar escrever uma extensão. Apesar desse tema parecer ir na contra-mão das tendencias (leia-se Frameworks), tem-se que em determinadas situações, isso para não dizer bem específicas, é necessário escrever suas funções diretamente em C/C++.
Já devo ter lido em algum lugar (não me lembro onde) que se caso você tenha uma função que seja muito usada, seria melhor escreve-la em C. Provavelmente a motivação de quem escreveu (e também a minha) é o ganho computacional que se tem, uma vez que o os códigos C/C++ são muito mais rápidos em comparação com os escritos em PHP.
Antes de iniciar a pesquisa para este post eu me deparei com uma dificuldade em especial: Falta de material de referencia, quando não ausente, está desatualizado. No manual do PHP que fala sobre este tema encontra-se algo, mas referente ao PHP 4, de acordo com uma viso logo no início. Mas como estamos apenas fazendo um experimento, vamos trabalhar com oque temos e no decorrer da série de posts, veremos o que acontece.
Antes de mais nada, consideremos alguns fatores como premissas:
- A abordagem será direta, dando o caminho das pedras do “como fazer”.
- Compreender a fundo o funcionamento interno do PHP é difícil, então vamos nos ater ao que interessa.
- O estudo pode ser árduo, então vamos praticar, tentar e retentar. A palavra chave vai ser transpiração.
- Você deve conhecer um pouco de C/C++? Mais a frente ele será necessário. Pretendo escrever sobre este assunto aqui no blog, em paralelo.
Para contextualizar e entender o que estamos nos propondo a fazer vamos dar uma olhadas nas possibilidades que temos, dada a arquitetura de funcionamento do PHP. Os itens adiante descrevem de acordo com o manual oficial as possibilidades de extensão da linguagem e alguns casos que já foram implementados.
1. PHP, o que é e como Funciona
O PHP é descrito como uma linguagem, e é por definição uma linguagem interpretada, e assim ela possui um interpretador, denominado Zend Engine, que é uma espécie de máquina virtual, assim como no Java (só que mais rápido). Sendo que um dos motivos que popularizou o PHP é justamente a capacidade de estender o seu interpretador! A função do interpretador (que também iremos chamar de núcleo ou core) é ler o código fonte e “traduzi-lo” em código executável – linguagem de máquina. O núcleo do PHP está escrito em C, e para estende-lo iremos utilizar o C++ (poderíamos utilizar o C, mas por razões que você verá durante a série será mais conveniente utilizar C++).
Bom, agora sabemos que o PHP possui um núcleo chamado Zend Engine que é responsável por compilar e executar nossos scripts, só que o PHP em si é um pouco maior do que isso (bem maior na verdade), e está divido em três partes:
- Interprete: Zend Engine, que faz o trabalho que descrevemos acima, se você quiser se aprofundar veja aqui e aqui.
- Funcionalidade: implementa as funções da linguagem, as que você já deve conhecer.
- Interface: Faz a interface com o servidor Web (e. g. Apache).
Na figura abaixo temos a a exemplificação da arquitetura do PHP, juntando os itens que citamos anteriormente:
Na figura você pode notar que todo acesso a banco de dados é feito pelos módulos, que são extensões do núcleo, e onde justamente nossa extensão vai estar. Ainda observando a figura tem-se o trajeto de ida e volta no paradigma cliente-servidor, onde a aplicação é solicitada no servidor web (1), por meio da interface (2) o Zend Engine é chamado, e em seguida irá buscar o script no disco do servidor (3), que será compilado e executado (4), nesse meio tempo o interpretador poderá acessar um dado módulo que é chamado no script, e após será compilado e executado (4). A resposta é enviada de volta a interface do servidor (5), que por sua vez enviará de volta ao navegador (6).
Agora sabemos que nosso ambiente de trabalho poderá estar em três seções, vejamos então quais são as possibilidades.
1.1 Extensões Externas
As funções externas são aquelas que pode ser carregadas externamente pela função dl(), tem-se que estes são casos muito específicos, pois dadas as desvantagens deste método o ganho de desempenho proposto no início do post não faz sentido, uma vez que estes carregamentos demandam muita memória (e tempo!). Dê uma olhada na tabela abaixo retirada do manual do PHP:
Vantagens | Desvantagens |
Os módulos externos não necessitam que você recompile o PHP. | É necessário carregar a extensão todas as vezes que for usa-la. |
O tamanho do PHP não é alterado. | É necessário fazer acesso ao disco (o que é muito lento) toda vez que o módulo for requisitado. |
O manual ainda cita que este é um método que pode ser usado caso você esteja em um ambiente compartilhado, o que é mais comum na maioria dos casos, pois não há possibilidade de recompilar o PHP com a extensão, ou modificar alguma diretiva no arquivo php.ini.
1.2 Build-in Modules
Como você já deve ter percebido esta é a abordagem que nos interessa: vamos desenvolver um módulo e compila-lo junto com o PHP, acredito que seja neste contexto que teremos o ganho de desempenho mais considerável. Uma das reflexões que podemos ter nesta abordagem é: Posso ter minha aplicação totalmente feita e compilada junto com PHP? Separei dois itens abaixo onde temos um parenteses sobre esta reflexão e outra que irá complementar o item 1.3, estes subitens não estão muito direcionados na nossa empreitada, no entanto que vale a pena ler.
Abaixo tem-se a tabela com as vantagens e desvantagens dessa abordagem, o conteúdo também foi adaptado do manual do PHP.
Vantagens | Desvantagens |
Não é necessário carregar explicitamente o módulo, ele apresenta-se como uma funcionalidade nativa do PHP. | Necessita de recompilar o PHP. |
Não existem arquivos externos a serem carregados. Tudo já está compilado junto com o PHP. | O PHP cresce e consumirá mais memória. |
Uma das desvantagens citadas é o aumento no consumo de memória. Não podemos esquecer que a boa programação do nosso módulo vai minimizar este efeito, e que seus malefícios também poderiam ser percebidos se a nossa extensão fosse implementada em código PHP; pense como exemplo a manipulação de imagens, no decorrer da nossa aboragem vamos analisar, como estudo de caso, o material do post do Francismo de Souza Júnior, onde ele desenvolve uma extensão para detecção de objetos utilizando a biblioteca OpenCV.
Uma das considerações mais obvias que temos é que nesta abordagem é necessário que, caso pretenda utilizar seu módulo como nativo no PHP, você tem há de dispor de um servidor onde possa modificar o PHP a seu gosto, como uma hospedagem dedicada, dado que vamos recompilar o PHP.
1.2.1 Algumas palavras sobre as modificações do Facebook, o HipHop
Em fevereiro de 2010 a equipe de desenvolvimento do PHP postou em seu blog uma novidade, o denomindado HipHop, que na verdade não é uma extensão, mas sim um PHP totalmente modificado, onde inicialmente tinha-se que ele realiza a transformação do código PHP em para C++, que por sua vez era compilado pelo g++. Dê uma olhada na figura abaixo para observar o processo:
De acordo com o post, a preocupação inicial era com o desempenho (consumo de CPU) das linguagens interpretadas frente as compiladas. No decorrer da narrativa o autor cita o desenvolvimento de extensões e argumenta que dado o tamanho da equipe e a complexidade que envolvia o desenvolvimento das tais extensões, transcrever as regras de negócio do Facebook inicialente escritas em PHP para código C++ seria um trabalho demasiado custoso, tendo em vista os aspectos como o conhecimento de C++ e da Zend API (nos aprofundaremos neste tópico nos próximos posts), por fim é citado que obteve-se um ganho de 50% na execução da aplicação.
Este é um assunto que cabe um post mais específico para investigar o assunto, pretendo em breve escrever algo sobre.
1.2.2 “Compilando” meu código PHP
De maneira mais simplória do que no HipHop, durante a pequisa para iniciar este post encontrei um post muito interessante no blog do Rafael Clares, que tratava a compilação de classes escritas em PHP em códigos C++ utilizando o módulo nativo do PHP, o bcompiler. Se você pensa em justamente compilar toda sua aplicação, creio que leitura do Rafael seja mais adequada.
1.3 Modificações no Zend Engine
Nossa terceira e ultima abordagem trata-se da modificação do Zend Engine. Como vimos o núcleo do PHP é responsável por compilar e executar o script em tempo de execução, então pode-se inferir que a modificação do interpretador apenas se justifica quando é necessário modificar o comportamento da linguagem. No manual é evidente que tais modificações não são recomendadas, pois resultariam em incompatibilidades e dada a característica da modificação, aumenta-se o acoplamento da aplicação (o que é um fator indesejado), e para dificultar ainda mais a implementação da extensão, não existe abordagem oficial no manual do PHP para tal. Lembrando que assim como no item 1.2 é necessário recompilar o PHP.
2. Conclusão da Primeira Parte
Bom amigos, chegamos a conclusão da primeira parte do nosso trabalho, agora já sabemos quais são as possibilidades para escrever extensões e citamos alguns exemplos de trabalhos parecidos. No próximo post vamos explorar a anatomia da extensão e configurar o ambiente de desenvolvimento, ainda não decidi se iremos explorar no Linux ou no Windows, estou inclinado a seguir no Windows porque notei alguns trabalhos já explorando o desenvolvimento no Linux, então algo novo seria mais apropriado.
Estou aberto a sugestões, críticas, elogios e qualquer outro tipo de contato! Até o próximo post!
3. Referencias
- Zend API – Hackeando o núcleo do PHP
- Wikipedia – Interpretador
- Como funcionam os Interpretadores
- Wikipedia – Zend Engine
- Zend Engine 2.0
- Francisco de Souza Júnior – Detectando Faces (ou outros objetos) com PHP e OpenCV
- Wikipedia – OpenCV
- Rafael Clares – Compilando classes PHP
- Facebook – HipHop for PHP: Move Fast
- Facebook libera HipHop Virtual Machine – iMasters
- Br-Linux – “HipHop”, o tradutor PHP do Facebook – aumenta o desempenho de execução, e também é servidor web
Abraços,