Cache de variáveis no PHP (Parte 2)
Na primeira parte desta série tratei da utilização da
palavra-chave static como forma de manter uma variável
PHP em cache. No exemplo dado, mantinha-se a tabela
“role” completa em cache (de fato apenas os campos “id”
e “name” eram mantidos, mas todas demais colunas da tabela
poderiam ter sido mantidas em cache).
Minha tabela “roles” possuirá, no máximo, em torno de 20 registros, e por isso um cache completo da tabela não foi problemático. Mas pode ser interessante realizar o cache de tabelas maiores, com muitos milhares de registros, por exemplo. E aí entra a técnica que a partir de agora chamarei de “cache preguiçoso”.
A idéia do cache preguiçoso é a seguinte: você sabe que terá
de carregar para a variável em cache (no nosso exemplo, $roles)
um grande número de registros, mas não sabe de antemão
quais são. Como carregar todos os registros de uma única vez
pode levar muito tempo e/ou consumir muita memória, podemos acessar
o banco apenas quando for necessário, sob demanda. Confira
o exemplo a seguir.
function get_role_id($name) {
global $db;
static $roles;
if (empty($roles)) {
$roles = array(); // inicializa o cache
}
if (array_key_exists($name, $roles)) {
print "NAO acessei o BD...\n";
$role_id = $roles[$name]; // cache nao eh atualizado
}
else if ($role_id = $db->get_role_id_from_name($name)) {
print "Acessei o BD...\n";
$roles[$name] = $role_id; // coloca mais um valor no cache
}
else {
$role_id = null;
}
return $role_id;
}
A implementação do cache preguiçoso é bastante simples. Na primeira vez
que a função é chamada o cache ($roles) é inicializado. Nas chamadas
subseqüentes verifica-se se $roles possui um valor associado à chave
que chega como parâmetro. Nas primeiras chamadas da função é natural
que as chaves ainda não existam, e o banco é acessado (através do
objeto $bd) para recuperar o registro em questão.
Quando uma chave que já foi recuperada do banco é solicitada novamente, então não é mais preciso acessar o banco de dados (ela está no cache!). O programa abaixo utiliza essa função e ilustra seu funcionamento.
print " id do papel 'admin' = " . get_role_id('admin')."\n";
print " id do papel 'editor' = " . get_role_id('editor')."\n";
print " id do papel 'guest' = " . get_role_id('guest')."\n";
print " id do papel 'admin' = " . get_role_id('admin')."\n";
print " id do papel 'editor' = " . get_role_id('editor')."\n";
print " id do papel 'guest' = " . get_role_id('guest')."\n";
print " id do papel 'writer' = " . get_role_id('writer')."\n";
A saída do programa:
Acessei o BD...
id do papel 'admin' = 1
Acessei o BD...
id do papel 'editor' = 2
Acessei o BD...
id do papel 'guest' = 4
NAO acessei o BD...
id do papel 'admin' = 1
NAO acessei o BD...
id do papel 'editor' = 2
NAO acessei o BD...
id do papel 'guest' = 4
Acessei o BD...
id do papel 'writer' = 3

December 1st, 2007 às 10:40 am
Algo que eu fico me perguntando: Esse cache é ‘global’? Digo global para funcionar para todos os usuários… Um cenário como: Usuário 1 acessa o script Usuário 1 sai Usuário 2 acessa o script Usuário 3 acessa o script Usuário 2 sai Usuário 3 sai A variável seria mantida em cache da mesma forma? Eu fico me perguntando como o PHP gerencia esse tipo de coisa, para mim cada acesso de usuário a um script seria como iniciar o programa a partir de um certo ponto e nosso único ’save’ seriam os cookies e as sessões… Estou errado? Acho que pode ter ficado meio confuso…
December 1st, 2007 às 12:49 pm
Como o protocolo HTTP não tem estados (duas requisições em um servidor provindas do mesmo cliente são encaradas como algo sem relação), acredito que essas variáveis
staticsão globais dentro do servidor web (seja Apache ou Lighttpd), ou seja, para todos os usuários.A única maneira que eu vejo onde poderíamos associar uma variável estática a um usuário em particular seria através de um cookie de sessão… e isso não seria nada bom, afinal o cookie fica na máquina do cliente (e por conseguinte essa variável
staticinteira ficaria dentro do seu computador). Já pensou que bizarro seria?Portanto, acho que a minha primeira suposição é o comportamento mais provável exercido pelos servidores web.
July 15th, 2008 às 3:21 pm
Quem diria Caio! Estava precisando fazer exatamente isso, ao digitar no google quem é o primeiro resultado?
Valeu a força… Seu artigo foi muito útil…
Agora falta eu criar vergonha na cara e começar a escrever alguma coisa também não?
Sucesso pra tu! []’s Zeh
July 15th, 2008 às 3:27 pm
Valeu, Zeca, sucesso pra ti tbm!