Cache básico com variáveis estáticas

por Jan Seidl em 30 de junho de 2009

Quando uma função é chamada mais de N vezes (para os neuróticos, mais de 1), costumamos empregar técnicas de caching (cacheamento de informações) para evitar que a lógica seja recalculada para retornar um valor já previamente calculado.

Na área da computação, cache é um dispositivo de acesso rápido, interno a um sistema, que serve de intermediário entre um operador de um processo e o dispositivo de armazenamento ao qual esse operador acede. A vantagem principal na utilização de uma cache consiste em evitar o acesso ao dispositivo de armazenamento – que pode ser demorado -, armazenando os dados em meios de acesso mais rápidos

Um dos níveis possíveis de cacheamento é através de variáveis locais e é recomendado para funções chamadas mais de N vezes na mesma execução e pode resultar em um ganho de performance absurdo tanto no código quanto no banco de dados atrás da operação.

Digamos que temos a seguinte função abaixo representada em PHP:

1
2
3
4
5
6
7
function loadAllData() {
    /* Realiza query no banco */
    /* Processa informação */
    /* Calcula valores */
    /* Processa valor em outra função */
    return $data; /* retorna o valor */
} // end :: function :: loadAllData

Implementando o cache com o uso de variáveis estáticas

As variáveis estáticas (do tipo static) mantém seu valor único dentre as instâncias da função ao longo da aplicação e estão implementadas em praticamente todas as linguagens de programação.

Veja abaixo a mesma função PHP com o cache em variáveis estáticas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function loadAllData($reset = false) {
 
    static $cache;
 
    if (!isset($cache)) || $reset):
    /* Realiza query no banco */
    /* Processa informação */
    /* Calcula valores */
    /* Processa valor em outra função */
        $cache = $data; /* Atualiza o cache */
    else:
        $data = $cache; /* Lê direto do cache */
    endif;
    return $data; /* retorna o valor */
} // end :: function :: loadAllData

O código acima verifica se a nossa variável $cache está definida e lê o valor diretamente dela caso verdadeiro. Caso contrário, roda a lógica e depois associa o valor computado à variável $cache.

NOTA: O parâmetro $reset foi adicionado para forçar que o valor seja atualizado.

Implementando o cache com variáveis estáticas em funções com parâmetros

Para isto, basta usarmos a variável que vai receber o cache como array associativo e então puxar a chave correspondente. Esta chave pode ser qualquer string baseada nos parâmetros informados para haver diferenciação / relação entre a chave e o que vai ser obtido nela. É imperativo que a relação com os parâmetros seja facilmente parseada.

Implementação em PHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function loadAllData($data_id, $time_start, $reset = false) {
 
    static $cache = array();
 
    $cacheKey = "{$data_id}_{$time_start}"; /* Chave que será utilizada para diferenciar as entradas no cache */
 
    if (!isset($cache[$cacheKey])) || $reset):
    /* Realiza query no banco */
    /* Processa informação */
    /* Calcula valores */
    /* Processa valor em outra função */
        $cache[$cacheKey] = $data; /* Atualiza o cache */
    else:
        $data = $cache[$cacheKey]; /* Lê direto do cache */
    endif;
    return $data; /* retorna o valor */
} // end :: function :: loadAllData

Implementando outros níveis de cache

Pode-se aninhar este cache com variáveis estáticas a outros caches como memcached.

Implementação de cache aninhado em PHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$m = new Memcached();
$m->addServer('localhost', 11211);
 
function loadAllData($data_id, $time_start, $reset = false) {
 
    static $cache = array();
 
    $cacheKey = "{$data_id}_{$time_start}"; /* Chave que será utilizada para diferenciar as entradas no cache */
 
    if (!isset($cache[$cacheKey])) || $reset):
        if (!$data = $m->get('loadAllData_'.$cacheKey)):
    /* Realiza query no banco */
    /* Processa informação */
    /* Calcula valores */
    /* Processa valor em outra função */
        endif;
        $cache[$cacheKey] = $data; /* Atualiza o cache */
    else:
        $data = $cache[$cacheKey]; /* Lê direto do cache */
    endif;
    return $data; /* retorna o valor */
} // end :: function :: loadAllData

E você, otimiza como?

Adicionar esta notícia no Linkk

1 Comentário
  1. Lucas Gomes permalink

    Muito bom exemplo, era isso que eu estava a precisar, fiz uma busca sobre static no google e achei o seu exemplo..

    que me foi bem util.
    vlw !

Deixe sua opinião

Nota: Seu endereço de email nunca será publicado.

Acompanhe os comentários por RSS