Cache de variáveis no PHP (Parte 2)

Em: 26/11/2007 Tags: Referencie do seu blog (Trackback)

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

Artigos relacionados:

4 respostas para “Cache de variáveis no PHP (Parte 2)”

  1. danielneis disse:

    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…

  2. Caio disse:

    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 static sã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 static inteira 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.

  3. José Ricardo Coelho disse:

    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

  4. Caio Moritz Ronchi disse:

    Valeu, Zeca, sucesso pra ti tbm!

Escreva um comentário (utilize o formato Markdown)