Tuning

Palestra apresentada no PHP Conference 2012

Posted on dezembro 2, 2012. Filed under: PHP, Tuning | Tags:, , |

Primeiramente gostaria de agradecer à organização, professores e palestrantes do evento. Houve muitas palestras interessantes, networking e troca de experiências. Achei o evento realmente enriquecedor. Não somente eu, mas meus amigos que estavam juntos tiveram a mesma opinião.

O tema da minha palestra foi Tuning Apache/MySQL/PHP para desenvolvedores. Conforme prometido no evento, pode ser baixado no link abaixo:

Tuning Apache/MySQL/PHP para desenvolvedores

Segue abaixo links para artigos que escrevi sobre o assunto:

Tuning Apache 2.x
Tuning no MySQL
PHP Profiler com xdebug e webgrind
Usando memcached no PHP
Usando APC (Alternative PHP Cache)
PHP – Opções de cache de opcode
PHP Caching com Zend_Cache
PHP e Computação em Nuvem com Zend_Cloud

Douglas-phpconf

Ler Post Completo | Make a Comment ( None so far )

PHP e Computação em Nuvem com Zend_Cloud

Posted on outubro 24, 2011. Filed under: PHP, Tuning, Zend Framework |

Muito se fala hoje me dia sobre computação em nuvem. Gostaria de abordar esse tema junto com a linguagem PHP. Nuvens oferecem ilimitados recursos para sua aplicação. Você tem diversas opções disponíveis de plataformas Cloud: Amazon, Rackspace, Microsoft, Google e diversas outras. A maioria delas oferecem dois tipos de serviços em Cloud, IaaS (Infrastructure-as-a-Service) e PaaS (Platform-as-a-Service):

IaaS (Infrastructure-as-a-Service) – As máquinas virtuais estão sob seu total controle. Você tem acesso root e portanto toda manutenção/instalação esta em sua responsabilidade. Incluíndo também o firewall, balanceamento, etc.

PaaS (Platform-as-a-Service) – Abordagem também através de máquinas virtuais. Porém o controle da infraestrutura não é sua responsabilidade. Você se preocupa somente com o desenvolvimento de sua aplicação. Para que isso seja possível, a plataforma de cloud computing disponibiliza APIs para que você possa interagir com a plataforma. Normalmente as APIs são disponibilizadas através de protocolo REST via WebService. Windows Azure, Amazon são exemplos desse tipo de arquitetura.

SimpleCloud

Como já citamos anteriormente temos diversas opções de plataformas para cloud. Cada uma dessas opções tem suas próprias APIs para interação com a plataforma. Gostaria de chamar atenção aqui para o projeto da Zend chamado SimpleCloud que tem o objetivo de fornecer uma camada de abstração para as APIs das plataformas de computação em nuvem. A boa notícia é que esse projeto transformou-se em um componente do Zend Framework, chamado Zend_Cloud. Baixe a última versão do Zend Framework para poder utilizar esse recurso.

Amazon

Como citei anteriormente, o Zend_Cloud fornece uma camada de abstração para plataformas de Cloud Computing. Portanto vamos utilizar os serviços de Cloud da Amazon como backend para os teste deste artigo. Poderíamos usar o Windows Azure ou outra opção disponpivel, porém neste artigo vamos trabalhar com a Amazon. Antes de continuar, será necessário criar uma conta no AWS da Amazon (gratuito). Acesse o link para criar sua conta.

Após criar a conta você precisará obter seu AWS Key e AWS Secret Key que serão utilizados para acessar os serviços de Cloud quer iremos ver mais adiante. Para obter as chaves, acesse o link Account -> Security Credentials.

Serviço de Storage

O serviço de Storage permite armazenar qualquer tipo de dados em qualquer hora de qualquer parte da web. Os tipos de armazenagem normalmente são imagens, arquivos para download, vídeos, distribuição de arquivos temporários, etc. Para disponibilizar os dados para usuários da sua aplicação, você pode disponibilizar links diretos, ou você pode construir um aplicação para intermediar o acesso. Lembre-se que aqui não deve ser armazenado arquivos da sua aplicação, mas arquivos para o usuário. (imagens, vídeos, arquivos para download, etc.)

O serviço de storage do Amazon chamá-se Amazon S3. Você precisa habilitar esse serviço na sua conta do Amazon. Para isso acesse o link abaixo:

http://aws.amazon.com/s3/

Você precisa informar um número de cartão de crédito válido. Você não será cobrado até que o serviço seja utilizado. Como estamos usando para testes, o valor cobrado será mínimo. Para você ter uma idéia, para testar os exemplos utilizados neste artigo gastei somente $0,03. No próprio link acima você pode consultar as tabelas de preço para esse serviço.

Para começar a armazenar seus arquivos no storage será necessário criar aquilo que chamamos de bucket. Todos dados são armazenados em buckets. Pense no bucket como se fosse um driver separado em seu computador. Lembre-se também que um bucket esta em um namespace compartilhado com todos os outros usuários do Amazon S3, portanto o nome do bucket tem que ser único.

Os arquivos armazenados no bucket são chamados de objetos. Podemos manter uma estrutura hierarquica dos objetos dentro dos buckets como se eles estivessem dentro de diretórios, como por exemplo, chamando o objeto de imagens/zend-logo.png.

Vamos criar o bucket através do console de gerenciamento da Amazon. Poderíamos ter feito através de código PHP utilizando sua API, porém vamos usar o console para facilitar nossa tarefa. Logado no site da Amazon com seu usuário, acesse o console de gerenciamento do S3 e crie o seu bucket clicando no botão Create Bucket.

Agora que temos um bucket, podemos criar nosso script php para inserir arquivos dentro do S3. Primeiro crie o arquivo cloud.ini onde iremos parametrizar os dados para acessar o storage. Dessa forma, você não precisa inserir esses dados em todos scripts que você for trabalhar com o Zend_Cloud:

cloud.storage_adapter="Zend_Cloud_StorageService_Adapter_S3"
cloud.aws_accesskey="XXXXXXXXXXXXXXXXXXXX"
cloud.aws_secretkey="1234567890123456789012345678901234567890"
cloud.bucket_name="pasquati"

Abaixo é o código usado para inserir arquivos no Storage da Amazon. Neste exemplo, estamos inserindo um logotipo do Zend Framework.

<?php
/* includes */
require_once ("Zend/Cloud/StorageService/Factory.php");
require_once ("Zend/Cloud/StorageService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do storage */
$storage = Zend_Cloud_StorageService_Factory::getAdapter($config->cloud);

/*
 * nome do objeto (id) que sera inserido no storage
 * Quando precisarmos acessar esse objeto utilizaremos esse nome
 */
$caminhoArquivo = 'imagens/zend-logo.png';

/* conteudo do arquivo que sera enviado ao storage */
$data = file_get_contents('zend-logo.png');

/*
 * inserindo o objeto no storage.
 * setamos permisao de leitura para todos usarios
 */

$storage->storeItem($caminhoArquivo, $data, array(
        Zend_Cloud_StorageService_Adapter_S3::METADATA => array(
            Zend_Service_Amazon_S3::S3_ACL_HEADER => Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ,
        )
));

echo "Arquivo enviado ao storage com sucesso!\r\n";

Por padrão, ao inserirmos um arquivo dentro do storage, ele possui permissões de leitura e gravação somente para o nosso usuário. Porém, no exemplo anterior, setamos permissão que qualquer pessoa na web possa acessar o nosso arquivo. Caso você queira disponibilizar os arquivos do storage na web, a URL deve ser montada de acordo com o modelo abaixo:

http://<bucket-name>.s3.amazonaws.com/imagens/zend-logo.png

ou

http://s3.amazonaws.com/<bucket-name>/imagens/zend-logo.png

Podemos também fazer o download dos arquivos do storage através de um script php. Segue abaixo exemplo do código que fará o download do logo da zend e o armazenará em disco.

<?php
/* includes */
require_once ("Zend/Cloud/StorageService/Factory.php");
require_once ("Zend/Cloud/StorageService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do storage */
$storage = Zend_Cloud_StorageService_Factory::getAdapter($config->cloud);

/*
 * nome do objeto (id) que sera obtido do storage
 */
$caminhoArquivo = 'imagens/zend-logo.png';

/* obtendo os dados do arquivo a partir do storage */
$dados = $storage->fetchItem($caminhoArquivo);

/* salvando o arquivo restaurado em disco */
file_put_contents("zend-logo-restaurado.png", $dados);

echo "Arquivo recebido do storage com sucesso!\r\n";

Document Service

O componente Document Service do Zend_Cloud abstrai funcionalidades do serviços como Amazon SimpleDB e Azure Table Storage. Conhecido como “bancos de documentos” são fontes de dados categorizados como banco de dados não-relacionais. É uma estrutura desenvolvida especificamente para alta perfomance, escabilidade e flexibilidade. O usuário não precisa se preocupar com administração do banco de dados mais, preocupa-se somente com o desenvolvimento da aplicação.

Para utilizar o Document Service fornecido pela Amazon, registre-se através do link http://aws.amazon.com/simpledb/.

Para utilizar o serviço configure o cloud.ini da seguinte forma:

cloud.document_adapter="Zend_Cloud_DocumentService_Adapter_SimpleDb"
cloud.aws_accesskey="XXXXXXXXXXXXXXXXXXXX"
cloud.aws_secretkey="1234567890123456789012345678901234567890"

Primeiramente iremos criar um collection onde iremos armazenar dados. Pense em collections como se fossem tabelas em um banco de dados relacional.

<?php
/* includes */
require_once ("Zend/Cloud/DocumentService/Factory.php");
require_once ("Zend/Cloud/DocumentService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do DocumentService */
$adapter = Zend_Cloud_DocumentService_Factory::getAdapter($config->cloud);

/* cria collection */
$adapter->createCollection("usuarios");

echo "Collection criada com sucesso \r\n";

Após criado o collection, podemos inserir documentos nele. Todo documento inserido deve ser identificado através do que chamamos de “Document ID”. Cada documento pode ter sua própria estrutura. Não é necessário que os documentos armazenados em um mesmo collection tenham a mesma estrutura.

Inserindo documentos no collection:

<?php
/* includes */
require_once ("Zend/Cloud/DocumentService/Factory.php");
require_once ("Zend/Cloud/DocumentService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do DocumentService */
$adapter = Zend_Cloud_DocumentService_Factory::getAdapter($config->cloud);

/*
 * ao obter a class do adpter, garantimos que eh uma classe
 * direta ou que extende Zend_Cloud_DocumentService_Document
 */
$class = $adapter->getDocumentClass();

/* chave primaria do registro */
$primaryKey = 'doug123';

/* dados que a serem inseridos no collection */
$doc = new $class(array(
        'nome' => 'Douglas',
        'apelido' => 'Doug',
        'email' => 'douglas.pasqua@gmail.com',
        'idade' => 29,
        'pais' => 'Brasil',
        'idioma' => 'PHP',),
        $primaryKey
);

/* insere os dados em uma collection (tabelas) */
$adapter->insertDocument("usuarios", $doc);

echo "Dados inseridos com sucesso\r\n";

Documentos podem ser obtidos através do ID ou através de “query” no collection.

<?php
/* includes */
require_once ("Zend/Cloud/DocumentService/Factory.php");
require_once ("Zend/Cloud/DocumentService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do DocumentService */
$adapter = Zend_Cloud_DocumentService_Factory::getAdapter($config->cloud);

/* montando a query */
$query = $adapter->select();
$query->where("email = ?", "douglas.pasqua@gmail.com");

/* fazendo a query no collection */
$r = $adapter->query('usuarios', $query);

/* iterando atraves dos dados obtidos na query */
foreach($r as $reg) {
        echo "Nome: " . $reg->nome . PHP_EOL;
}

Temos vários outros métodos para trabalhar com Documents no Zend Cloud, consulte a documentação para mais exemplos:

http://framework.zend.com/manual/en/zend.cloud.documentservice.html

Queue Service

O Queue Service permite um tipo de computação de dados de forma assíncrona. A implementação permite distribuir mensagens de forma confiável e escalável. Um exemplo de aplicação que utiliza esse serviço seria um “Job Dispatching”. O Frontend dispara o job para o Queue Service de forma assíncrona e temos uma outra aplicação que processa os jobs como se estivesse em background. Esse cenário pode ser útil em várias outras situações. Caso queira habilitar o Queue Serice da Amazon, é necessário habilitar o serviço na sua conta através do link http://aws.amazon.com/sqs/. Para exemplos de utilização no Zend Framework, acesse o link http://framework.zend.com/manual/en/zend.cloud.queueservice.html.

Conclusão

Abordamos aqui os 3 tipos de componentes disponibilizados pelo Zend_Cloud (Storage Service, Document Service e Queue Service). A grande vantagem o Zend_Cloud é que sua estrutura interna faz a abstração das APIs específicas para cada plataforma de computação em nuvem. Portanto caso precise migrar de uma plataforma para outra, será necessário apenas alguns ajustes. Um exemplo, migrar do Amazon para o Microsoft Azure os exemplos deste artigo pode ser feito com poucos ajustes. Amazon e Windows Azure disponibilizam diversos outros serviços de computação em nuvem além desses. Aconselho visitar as referências abaixo para aprender mais.

Referências

http://framework.zend.com/manual/en/zend.cloud.html
http://simplecloud.org/
http://aws.amazon.com/s3/
http://aws.amazon.com/simpledb/
http://aws.amazon.com/sqs/
http://www.microsoft.com/windowsazure/
http://aws.amazon.com/php/

Ler Post Completo | Make a Comment ( 2 so far )

PHP Caching com Zend_Cache

Posted on outubro 12, 2011. Filed under: PHP, Tuning, Zend Framework |

O Zend_Cache é um componete distribuído junto com o Zend Framework. Pode ser usado tanto como um módulo standalone ou junto com o framework. Muito flexível, permite que você decida o que quer fazer cache (frontend) e onde armazenar (backend). Ao configurar uma instância do Zend_Cache você deve informar dois grupos de opções. Um para o frontend e outro para o banckend. Existem vários frontends e backends disponíveis por padrão no Zend Framework. Todos frontends extendem a classe Zend_Cache_Core que provê funcionalidades genéricas de cache.

Tipos de frontends disponíveis

Além da possibilidade de usar o frontend Core que provê cache de dados de forma básica, o Zend_Cache permite vários outros tipos de cache de dados.

  • Class – Permite realizar o cache de objetos e de chamadas para métodos estáticos.
  • File – Realiza o cache de arquivos que são carregados para dentro do PHP.
  • Function – Realiza o cache do retorno de uma função.
  • Output – Utiliza o Output Buffering do PHP. Ideal para fazer cache parcial de uma página. Realizará o cache de tudo que estiver entre os métodos start() e end().
  • Page – Semelhante ao frontend de Output. Porém com o Page o cache é realizado com páginas completas somente.
  • Capture – Usando juntamente com o backend Static é utilizado para gerar páginas estáticas à partir de páginas dinâmicas. Portanto, as requisições subsequentes não precisam passar pelo PHP ou Zend Framework.

Tipos de backends disponíveis

  • File – Armazena os registros do cache em arquivos.
  • APC – Armazena os registros de cache em memória compartilhada pelo APC (Alternative PHP Cache).
  • Zend Server/ZendPlataform – Armazena os registro de cache usando a funcionalidade de Cache do Zend Server.
  • XCache – Armazena os registros de cache em memória compartilhada pelo XCacahe.
  • Sqllite – Armazena os registros de cache em um banco de dados SQLite.
  • Memcached/Libmemcached – Armazena os registros de cache em servidor memcached.
  • TwoLevels – Permite especificar dois outros backends para armazenar os registros de cache.
  • Static – Usando juntamente com o frontend Capture é utilizado para gerar páginas estáticas à partir de páginas dinâmicas. Portanto, as requisições subsequentes não precisam passar pelo PHP ou Zend Framework.

Exemplos

Abaixo vamos demonstrar um exemplo simples da utilização do Zend_Cache. O exemplo utiliza o frontend Core que faz cache de dados simples. Estamos utilizando o backend File para armazenar os dados. Não recomendo à utilização do backend File pois ele é mais lento do que outros backends, principalmente aqueles que utilizam memória compartilhada. Estou utilizando neste exemplo pois para você que simplesmente quer testar os exemplos não necessita de instalar programas adicionais além do php e Zend_Cache. O importante salientar é que independente do backend que você escolha, a sintaxe de utilização do Zend_Cache é totalmente transparente.

O exemplo abaixo faz o cache de um array de dados. Os dados são informações sobre usuários do sistema. Para instânciar o cache, informamos qual o frontend e qual o backend desejamos. Passamos também um array de opções para frontend e backend. Nas opções do frontend informamos que os dados devem ser serialziados antes de serem inseridos no cache, através da opção automatic_serialization. Isto evita o nosso trabalho de fazer um serialize dos dados antes de colocar no cache. Nas opções de backend informamos qual o diretório o Cache utilizará para armazenar os dados. Esta opção é obrigatória pois estamos utilizando o tipo File como backend. No caso, o diretório será /phpcache.

<?php
require_once("Zend/Cache.php");

// opcoes para frontend
$frontendOptions = array (
        'automatic_serialization' => true
);

// opcoes para backend
$backendOptions = array (
        'cache_dir' => '/phpcache'
);

// instanciar o cache
$cache = Zend_Cache::factory(
        'Core',
        'File',
        $frontendOptions,
        $backendOptions);

// utilizando o cache
$usuarios = $cache->load('usuarios');
if(!$usuarios) {
        // inserir dados no cache
        $usuarios = array(
                array('id' => 1, 'nome' => 'Manuel', 'email' => 'manuel@xxxxyy.com.br', 'telefone' => '011-1111-1111'),
        array('id' => 2, 'nome' => 'Pereira', 'email' => 'pereira@xxxxyy.com.br', 'telefone' => '011-2222-2222'),
    );
        $cache->save($usuarios, 'usuarios', array('usuario', 'admin'));
}

// dados do usuáo
echo "<pre>";
var_dump($usuarios);
echo "</pre>";

Retorno do exemplo acima:

Neste exemplo, gostaria de chamar à atenção para a função save do Zend Cache:

$cache->save($usuarios, 'usuarios', array('usuario', 'admin'));

Além de utilizarmos um identificador único para referênciar os dados no cache, ‘usuarios’, também utilizamos dois tags, ‘usuario’ e ‘admin’. Podemos portanto agrupar dados de cache através das tags. Dessa forma, podemos excluir, por exemplo, todos os dados no cache que tem associado a tag ‘admin’. Facilita a vida não ?

Limpando o Cache

Deletando todos dados no cache que possuem à tag ‘admin’ associado:

$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('admin'));

Deletando dados do cache especificando o identificador:

$cache->remove('usuarios');

Removendo todos dados do cache de uma única vez:

$cache->clean(Zend_Cache::CLEANING_MODE_ALL);

Fazendo Cache de classes

O Frontend Class do Zend_Cache permite o cache de objetos e de métodos estáticos. No exemplo abaixo estamos fazendo o cache de um objeto da classe Usuario. Para que funcione de acordo com o esperado, definimos a opção cached_entity no bloco de opções do frontend. Dessa forma, o Zend_Cache irá fazer o cache da saída de todos métodos públicos referente ao objeto dessa classe.

<?php

require_once("Zend/Cache.php");

/*
 * Classe Usuario para exemplificar o cache de classes do Zend_Cache
 */
class Usuario {
        private $nome1 = "Jose";
        private $nome2 = "Pedro";

        public function getNome($tipo) {
                if($tipo == 1) {
                        return $this->nome1;
                } else {
                        return $this->nome2;
                }
        }
}

// opcoes para frontend
$frontendOptions = array (
        'cached_entity' => new Usuario(),
);

// opcoes para backend
$backendOptions = array (
        'cache_dir' => '/phpcache'
);

$cache = Zend_Cache::factory(
        'Class',
        'File',
        $frontendOptions,
        $backendOptions
);

echo $cache->getNome(1) . PHP_EOL;
echo $cache->getNome(2) . PHP_EOL;

Resultado do exemplo acima:

Perceba que estamos chamando o método getNome() através da instância do Zend_Cache e não da instância da classe Usuario. A instância do Zend_Cache funciona como um proxy para a classe Usuario. Na primeira vez que chamarmos o método getNome(1), o cache irá chamar o método original. Nas chamadas subsequentes, o resultado virá do cache. O interessante à observar aqui é que o Zend_Cache reconhece os parâmetros passados para os métodos. Portanto getNome(1) será armazenado separadamente de getNome(2) dentro do cache. Inteligente não ?

Conclusão

Realmente me surpreendi com as funcionalidades disponíveis pelo Zend_Cache. É um sistema de cache extremamente flexível, fácil de configurar e muito poderoso. Para se aprofundar mais a documentação oficial do Zend Framework é a melhor opção. Lá você encontrará exemplos de utilização com todos tipos de frontend e backend.

http://framework.zend.com/manual/en/zend.cache.html

Ler Post Completo | Make a Comment ( 2 so far )

Monitorando consultas lentas no PostgreSQL

Posted on setembro 30, 2011. Filed under: PostgreSQL, Tips, Tuning |

Em um post anterior já vimos como monitorar consultas lentas no MySQL, vamos agora ver como habilitar o log de consultas lentas no PostgreSQL. Como já foi discutido, esse recurso é extremamente útil para identificar gargalos em aplicações, principalmente aquelas que recebem um alto tráfego de acesso. Identificar e otimizar consultas com alta duração, como por exemplo criando indíces, irá diminuir a carga de processamento do seu servidor.

Para habilitar o log de consultas lentas no postgres é bem simples. Edite o arquivo postgresql.conf, normalmente localizado em /etc/postgresql/8.4/main/postgresql.conf no caso do Ubuntu com postgresql versão 8.4 e identifique a linha:

#log_min_duration_statement = -1

Substitua por:

log_min_duration_statement = 500

Recarregue a configuração do postgresql:

service postgresql reload

Perceba que colocamos para logar todas consultas que durarem mais que meio segundo (500ms). Você pode ajustar esse valor de acordo com sua necessidade. Por exemplo, caso você tenha um site com alto tráfego de acesso e tiver várias consultas que durem mais que meio segundo, neste caso pode fazer uma grande diferença otimizar essas consultas. Sinta-se livre para aumentar ou diminuir esse valor de acordo com o ambiente de sua aplicação.

Para visualizar o log de consultas lentas, vá para o diretório de log do postgres e edite o arquivo de log mais recente. No meu caso o arquivo é /var/log/postgresql/postgresql-8.4-main.log. Abaixo é um exemplo de um registro que gerou o log de uma consulta com duração de 2041.457 ms:

2011-09-29 11:27:39 BRT LOG: duration: 2051.457 ms execute pdo_stmt_000000b4: select * from backuplog WHERE message LIKE '%xyz%'

Referências

http://www.postgresql.org/docs/8.4/static/runtime-config-logging.html

Ler Post Completo | Make a Comment ( None so far )

PHP – Opções de cache de opcode

Posted on setembro 28, 2011. Filed under: PHP, Tuning |

Como todos sabemos PHP é uma linguagem interpretada. Portanto toda vez que um script é executado, o engine do PHP precisa compilar o código fonte em algo que a linguagem de máquina possa entender. Resultando em um bytecode que no caso chamamos de opcode. O opcode é gerado em cada requisiçao. Imagine então o trabalho do php engine quando utilizamos um framework MVC onde existem vários arquivos para serem compilados em uma mesma requisição.

Para ajudar na otimização desse processo podemos utilizar um cache de opcode, da forma como vimos no post anterior sobre o APC. Mas como funciona exatamente um cache de opcode ? Quando uma nova requisição é realizada, antes do php compilar o código fonte, o software de cache intercepta e verifica se o opcode do script já existe no cache. Caso não exista, o sistema de cache passa para o php engine gerar o opcode e o armazena no cache. Nas requisições subsequentes para o mesmo script o opcode irá ser obtido à partir do cache e não será necessário ser compilado pelo engine do php novamente. Esse processo economiza de forma considerável o processamento de CPU no servidor. É claro que se houver mudanças no código fonte em um script que já tenha o opcode no cache, a mudança será identificada pelo sistema de cache que irá proceder com a devida atualização.

Já vimos em um post anterior como instalar e configurar o APC que é uma das opções disponíveis para cache de opcode. Abaixo vamos fazer uma análise breve de algumas das outras principais opções disponíveis.

Opções de aceleradores de código PHP

  • eAccelerator – É um fork do antigo e conhecido Turck MMCache.  Acelera o código PHP de 1 até 10 vezes. Suporta PHP 4 e 5, incluindo a versão 5.3. O projeto incluia também um PHP Encoder que foi descontinuado em 2006. Neste link é realizado um benchmarking comparando um desenpenho entre os caches APC, XCache e eAccelerator em uma aplicação rodando Drupal. O eAccelerator teve melhor desempenho nos requisitos de velocidade e utilização de memória. Com a utilização do cache a aplicação teve um ganho de velocidade em 3x.
  • APC – Alternative PHP Cache, é um cache de opcode livre e grátis, desenvolvido pela equipe de programadores do php. É o mais utilizado, distribuído através de um pacote PECL e será incluído no core do PHP à partir da versão 5.4. Fácil de instalar, principalmente em distribuições de Linux como o Ubuntu. Se você fizer uma pesquisa na internet sobre aceleradores php, o APC é o mais recomendado. Suporta todas versões do PHP.
  • XCache – É um cache bastante popular conhecido pelo desempenho e estabilidade. Foi criado pelo mesmo desenvolvedor do lighttpd. É muito comum em ambientes de produção que possuem grandes volumes de acesso. Esta disponível para as versões mais recentes do php, incluíndo  versões de php para Windows. Foi desenvolvido com o intuito de sanar as limitações existentes nas outras plataformas de cache de opcode.
  • Zend Server  –  É uma opção comercial que além de incluir o cache de opcode inclui diversas outras soluções interessantes para ajudar desenvolvedores. O configurador de cache do Zend_Server possui parâmetros interessantes que merecem atenção (Verificar este link). Ótima opção para quem deseja investir em uma ferramenta comercial para essa finalidade.

Conclusão

Na minha opinião APC, eAccelerator e XCache são ótimas opções de software livre de cache de opcode. Aconselho você experimentar essas opções e fazer sua escolha. Vejo muitos comentários positivos na internet sobre essas 3 opções.  Em minha experiência tive mais contato com APC portanto no momento é o meu favorito.  Utilizar um acelerador  para PHP aumenta significativamente o desempenho de  sua aplicação e geralmente a instalação de uma ferramenta desse tipo é simples.  Porém não se esqueça de dar atenção para outros métodos de otimização de sua aplicação. No meu blog existem várias dicas de tuning para melhorar o desempenho.

Referências

Espero que a leitura desse artigo junto com a referências abaixo te ajude a escolher a melhor opção de cache de opcode para sua necessidade.

http://www.ducea.com/2006/10/30/php-accelerators/
http://stackoverflow.com/questions/930877/apc-vs-eaccelerator-vs-xcache
http://2bits.com/articles/benchmarking-drupal-with-php-op-code-caches-apc-eaccelerator-and-xcache-compared.html

 

Ler Post Completo | Make a Comment ( None so far )

Usando APC (Alternative PHP Cache)

Posted on setembro 15, 2011. Filed under: PHP, Tuning | Tags:, , , |

APC, sigla de Alternative PHP Cache, é um cache de opcode que pode aumentar significativamente o desempenho da sua aplicação. Além de fazer o cache de variáveis/objetos, assim como o memcached, ele tem a função de fazer cache do próprio código compilado do php. De qual forma ? Para entender, é importante alguns conceitos básicos. Como todos sabemos, PHP é uma linguagem interpretada (Diferente de Java, C, etc.). Quando realizado uma requisição para uma página php, o engine do php lê o código fonte php, compila em um bytecode, chamado opcode, e finalmente o executa. Toda requisição passa por esse processo. O que o APC faz nesse processo ? Ele faz o cache do bytecode compilado (opcode) e o reutiliza nas requisições subsequêntes. Isto reduz o tempo de processamento no servidor. Em sites de alto tráfego, o desempenho pode melhorar significativamente.

O APC é distribuído através de um módulo PECL e pode ser facilmente instalado e habilitado em distribuições como Ubuntu através do comando abaixo:

$ sudo apt-get install php-apc

O comando acima irá instalar o módulo e reiniciar o apache automaticamente. Para checar se o APC foi instalado com sucesso e esta habilitado, crie um php com o comando phpinfo(); e verifique à presença da sessão apc conforme imagem abaixo:

phpinfo-apc

Junto com o pacote de instalação do APC é distribuído um script, apc.php, usado para administração do cache. Através dessa interface é possível visualizar à utilização do cache, como as variáveis e scripts contidos nele, entre outras coisas. Você precisa copiar o script apc.php para dentro do DocumentRoot do seu webserver. No Ubuntu pode ser feito da seguinte maneira:

$ cp /usr/share/doc/php-apc/apc.php.gz /var/www
$ cd /var/www
$ gunzip apc.php.gz

Edite o arquivo apc.php e especifique uma senha de sua preferência na linha 42 (no meu caso):

...
defaults('ADMIN_USERNAME','apc');                       // Admin Username
defaults('ADMIN_PASSWORD','password');          // Admin Password - CHANGE THIS TO ENABLE!!!

Acessando a interface administrativa do cache:

http://localhost/apc.php

Através da interface administrativa é possível visualizar informações relativas às páginas e variáveis em cache. É possível também limpar o cache do servidor (opcode) como também limpar o cache do usuário (referente à variáveis e objetos que o programador colocou no cache). Para limpar o cache é necessário logar como administrador através do link no canto superior direito. Para logar, utilize o usuário e senha setados no arquivo apc.php. É interessante navegar pelas opções para entender as informações ali contidas. Segue a tela administrativa:

Aconselho a limpar o cache de opcode, através do botão “Clear opcode Cache”, periodicamente. Essa opção esta disponível somente quando logado.

Exemplos de Utilização do cache

Assim como o memcached, podemos utilizar o apc para cache de dados na aplicação. Segue abaixo exemplo:

<?php

// verifica se os dados do usuário estão no cache
if ($usuarios = apc_fetch('usuarios')) {
        echo "Dados no Cache: ";
} else {
        // adiciona dados do usuário no cache
        $usuarios = array(
                array('id' => 1, 'nome' => 'Manuel', 'email' => 'manuel@xxxxyy.com.br', 'telefone' => '011-1111-1111'),
                array('id' => 2, 'nome' => 'Pereira', 'email' => 'pereira@xxxxyy.com.br', 'telefone' => '011-2222-2222'),
        );
        apc_add('usuarios', $usuarios);
}

echo "<pre>";
var_dump($usuarios);
echo "</pre>";

Ao acessar o script pela primeira vez, os dados são registrados no cache. Os acessos subsequentes obterão os dados do cache. Segue resultado:

Inserindo objetos no cache

Podemos também inserir objetos tranquilamente em nosso cache. As funções do apc já fazem a serialização do objeto antes de inserí-lo no cache e vice-versa na hora de obter o objeto do cache:

<?php

// classe para armazenar dados do usuario
class usuario {
        private $id;
        private $nome;
        private $email;
        private $telefone;

        public function setId($id) {
                $this->id = $id;
        }
        public function getId() {
                return $this->id;
        }

        public function setNome($nome) {
                $this->nome = $nome;
        }
        public function getNome() {
                return $this->nome;
        }

        public function setEmail($email) {
                $this->email = $email;
        }
        public function getEmail() {
                return $this->email;
        }

        public function setTelefone($telefone) {
                $this->telefone = $telefone;
        }
        public function getTelefone() {
                return $this->telefone;
        }
}

// verifica se objeto consta no cache
if ($usuario = apc_fetch('usuario')) {
        echo "Dados no Cache: ";
} else {
        // criar cache para objeto usuario
        $usuario = new Usuario();
        $usuario->setId(1);
        $usuario->setNome('Manuel');
        $usuario->setEmail('manuel@xxxxx.com.br');
        $usuario->setTelefone('11-1111-1111');

        apc_add('usuario', $usuario);
}

echo "<pre>";
echo $usuario->getId() . PHP_EOL;
echo $usuario->getNome() . PHP_EOL;
echo $usuario->getEmail() . PHP_EOL;
echo $usuario->getTelefone() . PHP_EOL;
echo "</pre>";

Resultado:

Mais algumas Dicas

Para limpar uma variável/objeto do cache:

apc_delete('usuarios');
apc_delete('usuario');

Limpando todos dados do Cache:

// limpando o cache de opcode
apc_clear_cache();

// limpando o cache do usuário
apc_clear_cache('user');

Armazenando variáveis no cache:

apc_store('usuario', $usuario);

A diferença entre apc_add e apc_store é que o apc_store sobrescreve o valor no cache caso o identificador já exista. O apc_add não sobrescreve dados já existentes no cache com o mesmo identificador.

Procurei demonstrar aqui uma introdução à utilização de cache no php com APC. Segue abaixo alguns links para se aprofundar mais:

http://www.php.net/apc
http://pecl.php.net/support.php
http://devzone.zend.com/article/12618

Ler Post Completo | Make a Comment ( 3 so far )

Usando memcached no PHP

Posted on agosto 22, 2011. Filed under: PHP, Tuning |

Memcached utilizando junto com php, permite você aumentar a perfomance de sua aplicação fazendo cache de dados na memória. Usar o memcached para carregar dados, ao invés de carregar de um banco de dados ou do sistema de arquivos, pode ter um grande impacto na perfomance de sua aplicação php.

A regra básica de utilização de cache é simples: Conforme o client (usuário) acessa seu site onde os dados são provenientes de um banco de dados ou qualquer outra fonte de informações, inicialmente esses dados são gravados em um cache, no nosso caso usando o memcached. Nas próximas requisições, ao invés de buscar as informações no banco de dados novamente, iremos primeiro checá-las se existem no cache e caso existindo, são retornadas do cache e não do banco de dados. Em um outro momento, caso essas informações sofrerem atualizações na sua fonte de dados (database, etc..), iremos destruir o cache no memcached e reiniciar o ciclo novamente. Normalmente utilizamos um id único para identificar uma porção de dados gravados ou lidos em um cache.

Somente por curiosidade, o Zend Framework disponibiliza um módulo de Cache que pode ser utilizado juntamente com o memcached. Iremos abordar esse módulo em um post futuro.

Instalando e habilitando memcached no PHP

$ sudo apt-get install memcached
$ sudo apt-get install php5-memcached

O php também disponibiliza a bilioteca memchache, através do pacote php5-memcache, porém aconselho utilizar a biblioteca mancached como citado acima pois é mais atual e implementa o protocolo do memcache de forma mais eficiente.

Verificando se o serviço do memcached esta no ar:

$ ps ax | grep memcached

Reiniciando Apache:

$ sudo service apache2 restart

Exemplos

Segue abaixo um exemplo simples da utilização do memcached com PHP. Os principais pontos aqui são os métodos get, que otem dados do cache usando uma chave para identificação e o método set, utilizado para inserir dados no cache, também utilizando uma chave para identificação.

<?php
// conectando no memcached
$m = new Memcached();
$m->addServer('localhost', 11211);

// checando dados no cache e carregando em $rows
if (!($rows = $m->get('lista_usuarios'))) {
    if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
        // dados não encontrados no cache. 
        // inserir no cache dados obtidos no banco
        // obter lista de usuarios do banco de dados
        // $rows = obter_lista_usuarios_db();
        $rows = array('joao', 'jose', 'maria');

        // inserindo dados
        $m->set('lista_usuarios', $rows);
    }
}

// acessando dados
var_dump($rows);

PS: No método set é possível especificar o tempo de expiração em segundos em que irá durar o cache. Caso seja omitido, é por tempo indeterminado. (nunca irá expirar).

Caso os dados do banco de dados forem modificados ou de alguma forma for determinado que o cache precisa ser atualizado existe a possibilidade de forçar a limpeza do cache através do método delete:

<?php
$m = new Memcached();
$m->addServer('localhost', 11211);

// verifica se houve modificacao na fonte de dados que esta em cache
// $dados_modificados = houve_atualizacao_dados();

$dados_modificados = true; // somente para este exemplo funcionar
if($dados_modificados) {
        $m->delete('lista_usuarios');
}

Somente lembrando que se você reiniciar o serviço do memcached, por padrão, os dados em cache serão perdidos.

Usando o memcached para armazenar dados da sessão

O memcached pode ser utilizado para outros propósitos no PHP, como por exemplo, no armazenamento de sessões. É útil no caso de estar utilizando load-balancing com o php. Ao invés de armazenar os dados de sessão em disco, todos servidores php que estão no balanceamento podem armazenar os dados de sessão em lugar centralizado, no caso, um servidor memcached. Dessa forma, caso o usuário que logou em um servidor, ao ser redirecionado para outro servidor durante o acesso no site, ele não perderá a sessão iniciada anteriormente, devido ao mecanismo de sessão estar centralizado no memcached.

Para habilitar o armazenamento da sessão no memcached, configure o php.ini dessa forma:

session.save_handler = memcached
session.save_path = "127.0.0.1:11211"

É isso ae, espero que tenham gostado. Sintam-se à vontade para postar comentários. Abraços!

Ler Post Completo | Make a Comment ( 2 so far )

PHP Profiler com xdebug e webgrind

Posted on julho 26, 2011. Filed under: PHP, Tuning |

Um dos principais fatores à se levar em consideração no desenvolvimento de um software é o desempenho, principalmente se houverem muitos acessos. A maioria dos desenvolvedores acabam deixando de lado uma ánalise mais profunda do desempenho da aplicação e isso gerá insatisfação e incomodo para o usuário final. Com a utilização principalmente de frameworks MVC e programação orientada a objetos, nossas aplicações PHP ganham bastante em qualidade, facilidade em manutenção e reutilização de código, porém teremos uma redução na parte de desempenho. O objetivo de nossa ánalise aqui é poder mostrar à você como podemos fazer para identificar gargalhos nas aplicações e agir em cima desses pontos mais lentos afim de melhorar o desempenho. Para ajudar na análise vamos utilizar a combinação xdebug + webgrind.

Xdebug

Xdebug é uma extensão do PHP com a finalidade de nos ajudar a debugar mais detalhadamente nossos scripts. Iremos abordar mais especificamente o Xdebug Profiler. O profiler do xdebug é uma poderosa ferramenta de geração de dados estatísticos com a finalidade de identificar gargalos, ajudando o desenvolvedor na árdua tarefa de melhorar o desempenho de suas aplicações. Os dados são gerados em um formato de arquivo compatível com cachegrind. Portanto além do xdebug precisamos instalar um programa que nos ajude à analisar os dados gerados no formato do cachegrind. As principais opções desse tipo de software que temos são o KCacheGrind e Webgrind. Neste artigo vamos explicar como instalar e configurar o Webgrind que é uma ótima opção disponível.

Instalando xdebug no Linux Ubuntu:

Para habilitar o profiler do xdebug no PHP é bem simples. Primeiro instale a extensão do xdebug:

$ sudo apt-get install php5-xdebug

Edite o arquivo:

$ sudo vim /etc/php5/apache2/conf.d/xdebug.ini

Insira a seguinte configuração:

zend_extension=/usr/lib/php5/20090626/xdebug.so
xdebug.profiler_enable = 1
xdebug.profiler_output_dir = /log/xdebug

A primeira linha é caminho onde esta localizado o arquivo referente à extensão xdebug.
A segunda linha habilita o profiler do xdebug que é o que nos interessa.
A terceira linha define o caminho onde os arquivos de saída do xdebug serão gerados. O PHP deve ter permissão para escrever neste diretório:

$ sudo chown www-data /log/xdebug

Reinicie o Apache:

$ sudo /etc/init.d/apache2 restart

Neste nomento o xdebug deve estar habilitado e gerando o log no diretório /log/xdebug. Para verificar se a extensão foi instalada corretamente, crie um novo arquivo php com a função phpinfo() e procure pela seção xdebug para se certificar que a extensão esta corretamente instalada.

Vamos agora à instalação do Webgrind.

Instalando WebGrind

Precisamos de um software que nos ajude a analisar os logs gerados pelo xdebug. O nosso escolhido é o webgrind. Segue abaixo os detalhes de como instalar o webgrind.

A instalação é bem simples. Basicamente é baixar o arquivo zip de instalação, descompactar ele dentro do documentroot de seu servidor web (É necessário que ele seja descompactado dentro de algum diretório que possa ser acessado através do seu domínio web):

$ cd /var/www
$ sudo wget http://webgrind.googlecode.com/files/webgrind-release-1.0.zip
$ unzip webgrind-release-1.0.zip

Configurando o Webgrind

O webgrind necessita de uma configuração inicial para poder funcionar corretamente. Edite o arquivo config.php dentro do diretório do webgrind. Configure as seguintes opções:

  • $storageDir – Caminho para diretório onde o webgrind irá armazenar arquivos cachegrind já processados. Este diretório deve ter permissão de escrita do usuário do apache/php.
  • $profileDir – Caminho para o diretório onde estão os arquivos de log gerados pelo xdebug. Por padrão o caminho utilizado é o especificado na diretiva xdebug.profiler_output_dir. Porém caso não tenha o xdebug instalado no mesmo servidor do webgrind você deverá especificar o caminho correto para essa opção.
  • $defaultTimezone  – Configure corretamente o fuso horário da sua região. No meu caso, foi definido para ‘America/Sao_Paulo’. Para ajudar à verificar corretamente o nome do fuso horário da sua região acesse o link http://php.net/manual/en/timezones.php

Exemplo arquivo config.php:

static $storageDir = '/webgrind';
static $profilerDir = '/log/xdebug';
...
static $defaultTimezone = 'America/Sao_Paulo';
...

Neste momento o webgrind já pode ser acessado:

http://localhost/webgrind

Tela Webgrind

O webgrind disponibiliza informações detalhadas à respeito das requisições realizadas em sua aplicação php, como por exemplo:

  • Se o tempo esta sendo gasto em funções internas ou em funções definidas pelo usuário.
  • Exibe de onde as funções são chamadas e quais funções elas estão chamando.
  • Gerenciar o tempo gasto exibindo no formato “Total Self Cost” e “Total Inclusive Cost”. “Inclusive Cost” é o tempo gasto dentro da função + chamadas para outras funções.

É importante utilizar o webgrind por algum tempo até se familiarizar com ele. Através dele consegui facilmente identificar pontos na aplicação que poderiam ser melhorados. Conheciumento pelo menos em nível intermediário em php é necessário.

Boa sorte!

Ler Post Completo | Make a Comment ( 1 so far )

Tuning Apache 2.x

Posted on julho 19, 2011. Filed under: Linux, Tuning |

O objetivo deste artigo é ajudar você a melhorar o desempenho do seu servidor web Apache. Da versão 1.3 para versão 2.x aconteceram diversas melhorias relacionadas ao desempenho. Porém ainda é possível melhorar ainda mais a perfomance manipulando alguns parâmetros de configuração. O Objetivo aqui é abordar os principais parâmetros de configuração que possam influenciar diretamente na perfoamance.

Hardware

O principal fator no hardware que afeta a perfomance do Apache é memória. Monitore seu servidor para que ele nunca precise utilizar memória da swap. Você pode controlar a quantidade de memória utilizada pelo servidor através do parâmetro MaxClientes como veremos mais adiante. Além disso, procure sempre ter placas de redes, discos e cpus mais rápidos possíveis.

AllowOverride

Caso você esteja utilizando a solução AllowOverride junto com .htaccess, o Apache irá tentar abrir o arquivo .htaccess em cada requisição efetuada para o servidor prejudicando a perfomance. Por exemplo, caso você utilize:

DocumentRoot /var/www
<Directory />
  AllowOverride All
</Directory>

Ao chegar uma requisição para /index.html, o Apache irá tentar abrir os arquivos /.htaccess, /var/.htaccess e /var/www/.htaccess em todas requisições recebidas. Para evitar essa sobrecarga no servidor, se possível, desabilite a opção AllowOverride:

DocumentRoot /var/www
<Directory />
  AllowOverride None
</Directory>

Procure transportar toda configuração que você tiver dentro dos arquivos .htaccess para a configuração principal do apache ou virtual host. Por exemplo, caso você tenha a configuração no arquivo /var/www/protegido/.htaccess:

Deny from all

Transportando para o virtual host na configuração do apache:

<Directory "/var/www/protegido/">
  Deny from all
</Directory>

ExtendedStatus

Caso esteja usando mod_status para monitorar os processos do apache garanta que a opção ExtendedStatus esteja Off caso contrário o apache irá realizar diversas chamadas adicionais no sistema para cada requisição recebida.

<Location /server-status>
  SetHandler server-status
  ExtendedStatus Off
  Order deny,allow
  Deny from all
  Allow from localhost ip6-localhost
</Location>

SymLinks

A opção FollowSymLinks diz ao apache para seguir todos os links simbólicos do diretório. Caso essa opção esteja Off o Apache irá executar processos extras para verificar se o diretório ou arquivo não é um link simbólico. Portanto deixe essa opção sempre habilitada quando possível:

DocumentRoot /www/htdocs
<Directory />
  Options FollowSymLinks
</Directory>

Caso necessite de uma segurança maior e queira usar a opção SymLinksIfOwnerMatch ao invés da FollowSymLinks lembre-se que téra um custo maior nesse caso, pois a opção SymLinksIfOwnerMatch fará com que o apache verifique se o usuário dono do link corresponde ao mesmo usuário dono do destino do link. Então use-a com critério. Outra opção é a configuração abaixo, que faz com que a utilização SymLinksIfOwnerMatch seja menos custosa:

DocumentRoot /www/htdocs
<Directory />
  Options FollowSymLinks
</Directory>

<Directory /www/htdocs>
  Options -FollowSymLinks +SymLinksIfOwnerMatch
</Directory>

Essa última configuração evita checagens extras no DocumentRoot.

KeepAlive

A opção KeepAlive permite que o apache trabalhe com conexões persistentes, ou seja, é possível que milhares de requisições sejam tratadas em uma mesma conexão TCP. Habilitar essa opção reduz significativamente a carga do sistema.

Segue abaixo a configuração para ser inserida no arquivo de configuração do Apache, habilitando o KeepAlive:

KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 3

A diretiva MaxKeepAliveRequests determina o número máximo de requisições permitidas para uma conexão persistente. Defina um valor alto para uma melhor perfomance.

A diretiva KeepAliveTimeout determina o número de segundos que o Apache irá aguardar por uma subsequente requisição antes de fechar a conexão persistente. Defina para um valor pequeno. Valores altos poderão prejudicar a perfomance. Quanto maior o valor, maior o número de processos ficarão ocupados esperando por requisições enquanto não chega no timeout especificado.

MaxClients

A opção MaxClients determina o número limite de conexões simultâneas tratadas pelo Apache. Caso a conexão não possa ser tratada, pois chegou no limite máximo de conexões simultâneas, a conexão será colocada em uma fila. Essa diretiva influencia diretamente na performance do servidor. Caso seja definida um número pequeno, poderá estar consumindo pouco recurso do servidor, deixando-o ocisoso. Setar para um valor muito alto, poderá consumir 100% dos recursos, principalmente memória. Uma regra para calcular um número ideal para essa diretiva, é determinar a média do tamanho de um processo do apache, através de um comando como o top, e dividir pela quantidade de memória disponível, deixando, é claro, na suas contas, uma quantidade de memória para outros processos.

Segue a equação:

MaxClients ≈ (RAM - qtde memória para outros processos)/(média do processo apache)

Para obter quantidade de memória disponível no sistema: (Verificar -/+ buffers/cache: para obter quantidade de memória livre).

# free -m

Para ajudar a calcular o tamanho médio do processo do apache, pode utilizar top, ou o comando ps. Segue o comando ps abaixo para ajudar:

# ps -ylC apache2 --sort:rss

Espeque que alguma dessas dicas possa tê-lo ajudado a tornar seu apache mais rápido. Abraço!

Ler Post Completo | Make a Comment ( None so far )

Tuning no MySQL

Posted on abril 22, 2011. Filed under: MySQL, Tuning |

Neste Post iremos abordar alguns parâmetros da configuração do MySQL que influenciam na perfomance do banco de dados. A idéia é que você, leitor, tenha conhecimento para poder manipular esses parâmetros e melhorar o desempenho do seu banco de dados. Estou abordando somente alguns parâmetros envolvidos: max_connections, table_cache, thread_cache_size, query_cache_size.  Existem outros parâmetros que podem ajudar a melhorar a perfomance, mas irei abordar em posts futuros.

max_connections:

Determina o número máximo de conexões simultâneas permitidas. Por padrão o valor é 100. Caso sua aplicação esteja recebendo a mensagem de erro “Too many connections” significa que estourou o limite máximo de conexões simultâneas, portanto esta na hora de aumentar o valor desse parâmetro. O valor desse parâmetro influência no consumo de memória do servidor, portano esteja atento à esse ponto. Para monitorar as conexões ativas no momento, use o comando SHOW PROCESSLIST no console do mysql. Exemplo:

mysql> show processlist\G
*************************** 1. row ***************************
Id: 1
User: internet
Host: 192.168.0.10:36461
db: testedb
Command: Sleep
Time: 0
State:
Info: NULL
*************************** 2. row ***************************
Id: 2
User: internet
Host: 192.168.0.10:36460
db: testedb
Command: Sleep
Time: 0
State:
Info: NULL
*************************** 3. row ***************************
Id: 3
User: internet
Host: 192.168.0.10:36461
db: testedb
Command: Query
Time: 0
State: Writing to net
Info: select * from tabela_teste
3 rows in set (0.00 sec)

Nesse exemplo, no momento da excução do comando SHOW PROCESSLIST, haviam 3 processos simultânos em execução. A saída traz outras informações interessantes conforme podem observar acima. Exemplo:

max_connections = 200

PS: Esses parâmetros devem estar setados na sessão [mysqld] do arquivo my.cnf

table_cache:

table_cache é o número de tabelas abertas em cache para todos threads. Aumentar esse valor aumenta o número de file descriptors que o MySQL irá precisar abrir para trabalhar. Esse parâmetro esta relacionado com o max_connections: Caso tenha o valor de 200 para max_connections, você deve setar table_cache para 200 * N, onde N é o número máximo de tabelas usada por join em qualquer das queries que você estiver usando na sua aplicação. Aumentar muito o valor desse parâmetro pode fazer com que o MySQL exceda o número máximo de file descriptors abertos por processo. Este é um limite definido pelo S.O. Tenha certeza que o seu S.O.  permita abrir o número de file descritptors definido em table_cache. No Linux, para checar o número máximo de file descriptors permitidos use o comando abaixo:

# cat /proc/sys/fs/file-max
2210424

Exemplo:

table_cache = 800

PS: Esses parâmetros devem estar setados na sessão [mysqld] do arquivo my.cnf

query_cache_size:

É a quantidade de memória alocada para o cache de resultado de queries. O valor padrão é 0. Isso siginifica que o cache é desabilitado por padrão. Os valores permitidos são múltiplos de 1024.  O valor mínimo para esse parâmetro é 40Kb, reservado para alocação de suas estruturas. O tamanho exato depende da arquitetura do sistema. Aconselho setar o valor por volta de 128M, é claro que você deve avaliar a estrutura do seu servidor antes de trabalhar com esses valores, principalmente memória.

query_cache_size = 128M

PS: Esses parâmetros devem estar setados na sessão [mysqld] do arquivo my.cnf

thread_cache_size:

Quantidade de threads que  o servidor irá cachear para re-utilização. Quando um cliente desconecta a thread irá para um cache podendo dessa forma ser reutilizadaDessa maneira diminuimos a criação de novas threads para atender novos clientes. Esse parâmetro pode ser aumentado para melhorar a performance caso seu servidor tenha muitas conexões por segundo.  Através de um cálculo utilizando o número de conexões criadas e o número de threads novas criadas é possível determinar a eficiência desse cache, e então determinar um valor mais apropriado para esse parâmetro. A taxa de acerto baseado no cálculo abaixo deve estar o mais próximo possível de 99%:

100 - ((Threads_created / Connections) * 100)

Threads_created é o número de thread criadas desde que o MySQL foi iniciado. Connections é o número total de conexões criadas desde que o servidor do MySQL foi iniciado.  Nossa intenção é que o número de threads criadas seja o menor possível em relação ao número total de conexões realizadas.

Para obter o número de threads criadas, execute o comando abaixo no console do mysql:

mysql> SHOW STATUS LIKE '%thread%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Delayed_insert_threads | 0     |
| Slow_launch_threads    | 0     |
| Threads_cached         | 30    |
| Threads_connected      | 5     |
| Threads_created        | 600   |
| Threads_running        | 1     |
+------------------------+-------+
6 rows in set (0.00 sec)

O campo que nos interessa na lista acima é o Threads_created, valor 600. Portanto, desde que o MySQL foi iniciado somente 600 threads novas foram criadas.

Para obter o número de conexões criadas desde a inicialização do MySql, execute o comando abaixo no console do MySQL:

mysql> SHOW STATUS LIKE '%connections%';
+----------------------+----------+
| Variable_name        | Value    |
+----------------------+----------+
| Connections          | 10000    |
| Max_used_connections | 600      |
+----------------------+----------+
2 rows in set (0.00 sec)

O valor que nos interessa é o 10000.  Vamos agora ao nosso cálculo:

100 - ((600 / 10000) * 100)

O Resultado é 94% (significa que 94% das conexões utilizaram threads em cache). O ideal é que o resultado esteja pelo menos por volta de 99%. Portanto, o valor do nosso parâmetro, thread_cache_size, esta baixo e precisa ser aumentado. Aconselho ir aumentado esse campo até que o nosso calculo resulte por volta de 99%. No exemplo acima, o valor do campo thread_cache_size esta 30. Podemos ir aumentando de 10 em 10 até que cheguemos no resultado desejado.

Exemplo:

thread_cache_size = 60
PS: Esses parâmetros devem estar setados na sessão [mysqld] do arquivo my.cnf

O objetivo deste post foi abordar alguns parâmetros do MySQL que influenciam no desempenho do banco de dados. Não abordei todos, porém ao trabalhar com esses parâmetros acima o desempenho do seu banco irá melhorar de forma significativa. Já tive grandes resultados fazendo esses tunings em um banco que recebe muitos acessos. Espero que aproveitem.





Ler Post Completo | Make a Comment ( 6 so far )

« Entradas Anteriores

Liked it here?
Why not try sites on the blogroll...

%d blogueiros gostam disto: