Cache com PHP usando APC

Cache com PHP usando APC

Desemepnho de aplicações é cada vez mais importante. A Web está mais cheia de conteúdo a cada dia. E, consequentemente, as páginas tendem a possuir mais dados. Se não tomarmos cuidado com o desempenho, nossos sistemas ficarão lentos.

Uma forma de contornar esse problema é fazer cache de dados usados com frequência. Há várias maneiras de fazer cache com PHP. Neste artigo, vou falar do APC (Alternative PHP Cache), que é uma extensão do próprio PHP muito simples de usar.

O Que é Cache?

Segundo a Wikipedia, 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”. Ou seja, cache é um local de rápido acesso a informações que ficam salvas em um dispositovo cujo acesso é mais lento.

Por exemplo, um arquivo em disco pode ter seu conteúdo armazenado em cache na memória. O tempo de acesso à memória é muito mais rápido que o de acesso ao disco. Por isso é útil fazer cache em memória de arquivos acessados frequentemente.

O Que é o APC?

APC (Alternative PHP Cache) é uma extensão do PHP. Ela faz cache de dados em memória. Basta dizer qual será a “chave” (um identificador único para o dado salvo), qual é a informação a ser salva e por quanto tempo ela deve ser mantida em cache. O resto é tarefa do PHP.

A extensão APC não vem habilitada por padrão. É necessário habilitá-la em seu php.ini, ou instalar o pacote correspondente, caso tenha instalado o PHP a partir dos pacotes para Linux ou Mac OS X.

Como Usar o APC Para Fazer Cache com PHP

Existem algumas funções do APC, mas vou me ater às seguintes:

  • apc_add: adiciona um dado ao cache, caso ainda não esteja salvo;
  • apc_clear_cache: limpa o cache do APC;
  • apc_delete: remove um valor do cache;
  • apc_exists: verifica se uma determinada chave existe no cache;
  • apc_fetch: retorna um valor salvo no cache;
  • apc_store: salva um valor no cache, sobrescrevendo-o, caso já exista.

Adicionando um Valor ao Cache

Para adicionar um valor ao cache, é possível usar apc_add ou apc_store. A única diferença entre essas duas funções é que apc_add adiciona um dado ao cache apenas se ele ainda não existir. Já apc_store sempre adiciona o dado. Consequentemente, apc_store vai sobrescrever a informação, caso ela já tenha sido armazenada anteriormente.

A sintaxe de ambas as funções é a mesma, desta forma:

bool apc_add ( string $key , mixed $var [, int $ttl ] )
bool apc_store ( string $key , mixed $var [, int $ttl ] )

O parâmetro $key é a chave de identificação para a informação no cache. É esse valor que usaremos para buscar ou remover o dado do cache. O parâmetro $var é o valor a ser armazenado no cache. Ele pode ser uma simples variável, um array ou mesmo um objeto. E o parâmetro $ttl (Time To Live) é o tempo, em segundos, que o dado deve permanecer em cache. Se $ttl não for especificado (ou for 0), o dado será mantido em cache até que seja manualmente removido.

Para exemplificar, vamos inserir alguns dados no cache, todos com tempo de vida de 60 segundos:

$a = 'valor a';
apc_add( 'chave_a', $a, 60 );
 
$arr = [
    'a' => 1,
    'b' => 2
];
apc_add( 'meu_array', $arr, 60 );
 
$obj = new stdClass;
$obj->nome = 'Beraldo';
apc_add( 'meu_objeto', $obj, 60 );

Retornando Dados Salvos no Cache

Para retornar um dado salvo no cache, usamos a função apc_fetch. Basta passar como parâmetro a chave que utilizamos em apc_add ou em apc_store.

$a = apc_fetch( 'chave_a' );
var_dump( $a );
 
$arr = apc_fetch( 'meu_array' );
var_dump( $arr );
 
$obj = apc_fetch( 'meu_objeto' );
var_dump( $obj );

Se os dados estiverem em cache, var_dump os exibirá. Caso contrário, será retornado FALSE.

Verificando a Existência de um Dado no Cache

Antes de retornar o dado com apc_fetch, podemos usar apc_exists para verificar se a chave existe no cache. Assim, podemos alterar o trecho anterior pelo seguinte.

if ( apc_exists( 'chave_a' ) )
{
    $a = apc_fetch( 'chave_a' );
    var_dump( $a );
}
else
{
    echo "Chave chave_a não está no cache";
}
 
 
if ( apc_exists( 'meu_array' ) )
{
    $arr = apc_fetch( 'meu_array' );
    var_dump( $arr );
}
else
{
    echo "Chave meu_array não está no cache";
}
 
if ( apc_exists( 'meu_objeto' ) )
{
    $obj = apc_fetch( 'meu_objeto' );
    var_dump( $obj );
}
else
{
    echo "Chave meu_objeto não está no cache";
}

Removendo Um Dado do Cache

Para remover um dado específico, usamos apc_delete.Basta passar a chave por parâmetro, desta forma:

apc_delete( 'chave_a' );
apc_delete( 'meu_array' );
apc_delete( 'meu_objeto' );

Limpando Todo o Cache

Para limpar o cache completamente, basta usar a função apc_clear_cache:

apc_clear_cache();

Dessa forma, todos os dados salvos em cache serão apagados.

Comparando Desempenho

Para mostrar a diferença de tempo entre acessar um dado em disco e outro dado em cache, vou mostrar uma comparação de desempenho entre ambos.

Para isso, usarei um arquivo .ini, que é geralmente utilizado para armazenar configurações do sistema. Caso você não saiba trabalhar com arquivos .ini usando o PHP, recomendo que leia este meu post, onde mostro como fazer isso.

Critério de Avaliação

Para avaliar o desempenho, usarei apenas o tempo de execução da tarefa em questão. Usarei a função microtime, que retorna a hora atual, em microssegundos. Tendo a hora de início e a hora de término, basta subtraí-las e teremos o tempo de execução total. Vou considerar apenas o tempo de acesso ao dispositivo (disco e cache), sem considerar o tempo para exibir o dado na tela. Para exibir o resultado, usarei number_format, pois, quando o tempo é muito pequeno, o número é exibido em notação científica (no formato 5.124E-10) e pode confundir quem não está habituado a visualizar números nesse formato.

Arquivo de Configuração

Primeiramente, crie um arquivo chamado config.ini, com o seguinte conteúdo:

[db]
host = "localhost"
user = "usuario"
pass = "senha"
dbname = "nome_do_banco"

Esse é um simples exemplo de um arquivo .ini, com configurações para acesso a um banco de dados.

Carregando Dados do Arquivo

Vaamos agora criar o script que carrega uma configuração diretamente do arquivo.

$configFile = 'config.ini';
 
$start = microtime( true );
$config = parse_ini_file( $configFile, true );
$host = $config[ 'db' ][ 'host' ];
$end = microtime( true );
 
var_dump( $host );
var_dump( number_format( $end - $start, 20 ) );

No meu computador, o tempo de execução exibido foi 0.00008392333984375000.

Carregando Dados do Cache

Nesse script, vamos carregar o conteúdo do arquivo .ini e salvá-lo no cache. Apenas depois disso vamos contabilizar o tempo. Afinal, estamos interessados apenas no tempo de acesso ao cache.

$configFile = 'config.ini';
$configArr = parse_ini_file( $configFile, true );
 
apc_store( 'config', $configArr, 5 );
 
$start = microtime( true );
$config = apc_fetch( 'config' );
$host = $config[ 'db' ][ 'host' ];
$end = microtime( true );
 
var_dump( $host );
var_dump( number_format( $end - $start, 20 ) );

O resultado retornado foi 0.00001096725463867188.

Comparando os Resultados

O tempo de execução do primeiro script foi de 0.00008392333984375000 segundos. O segundo levou 0.00001096725463867188. Se dividirmos ambos os números, veremos que o script que acessa o cache rodou, aproximadamente, 7.652174 vezes mais rápido!

Conclusão

O uso de cache acelera bastante a execução dos nossos sistemas.

O APC é apenas uma das opções de cache para PHP. Existem diversas outras. Não importa muito qual você usará, mas é importante que seja usado cache para armazenar informações que são acessadas com frequência, como dados de um arquivo de configuração, como usei no exemplo.

 

The following two tabs change content below.
Graduado em Ciência da Computação, pela Universidade Federal do Paraná (UFPR), é desenvolvedor de software desde 2008, com foco em Desenvolvimento Web com PHP.