O documento discute técnicas para otimizar o desempenho de websites desenvolvidos em PHP. Ele aborda ajustes que podem ser feitos no servidor web e no banco de dados para melhorar a performance, como utilização de módulos do Apache, configuração do MySQL e uso de cache. Além disso, apresenta técnicas de profiling em PHP para identificar gargalos e otimizações como compactação de arquivos e static assets.
2. FELIPE RIBEIRO
• Graduando (concluinte) em Ciência da Computação na UFCG
• Zend Certified Engineer - PHP5
• Trabalha
como desenvolvedor Web e consultor com foco em
performance e escalabilidade de Websites
• Experiência em grids computacionais e sistemas distribuídos
• Membro fundador do grupo PHP-PB
• Contribuidor do PHP e Mozilla Camino
3. OBJETIVO
•O objetivo desse mini-curso é apresentar alguns dos conceitos
utilizados na otimização da performance e escalabilidade de web
sites
•A abordagem utilizada será bottom-up, ou seja, iniciaremos de
ajustes no servidor e back-end, para depois ajustarmos o front-
end
• Em aplicações práticas, essa abordagem depende do problema.
• Quem está “sofrendo” mais? Servidor ou cliente?
4. Performance
a habilidade que uma
aplicação tem de atingir um
objetivo, como por exemplo
responder no menor tempo
possível
20. Macintosh:~ felipe$ ab -c 10 -t 30 -k 'http://shoprizer.localhost/'
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking shoprizer.localhost (be patient)
Finished 4379 requests
Server Software: Apache/2.0.59
Server Hostname: shoprizer.localhost
Server Port: 80
Document Path: /
Document Length: 22320 bytes
Concurrency Level: 10
Time taken for tests: 30.010 seconds
Complete requests: 4379
Failed requests: 0
Write errors: 0
Total transferred: 99436344 bytes
HTML transferred: 97806240 bytes
Requests per second: 145.92 [#/sec] (mean)
Time per request: 68.532 [ms] (mean)
Time per request: 6.853 [ms] (mean, across all concurrent requests)
Transfer rate: 3235.74 [Kbytes/sec] received
21. Macintosh:~ felipe$ siege -b -t30s 'http://shoprizer.localhost/'
** SIEGE 2.67
** Preparing 10 concurrent users for battle.
The server is now under siege...
Lifting the server siege... done.
Transactions: 4909 hits
Availability: 100.00 %
Elapsed time: 29.84 secs
Data transferred: 104.49 MB
Response time: 0.06 secs
Transaction rate: 164.51 trans/sec
Throughput: 3.50 MB/sec
Concurrency: 9.93
Successful transactions: 4909
Failed transactions: 0
Longest transaction: 2.28
Shortest transaction: 0.00
25. • Instale a extensão Xdebug
a opção xdebug.profiler_enable
• Habilite
caso queira que toda execução gere o log
• Ou a opção
xdebug.profiler_enable_trigger para que
o log só seja gerado quando você passar
?XDEBUG_PROFILE na URL
26. • Rode o script que você quer analisar
• Abra
o log gerado pelo Xdebug no
KCacheGrind caso use Linux, ou no
WebGrind em qualquer outra plataforma.
29. • xdebug_memory_usage( ) diz quanto de
memória o script está usando no momento
da chamada
• xdebug_peak_memory_usage( ) diz qual o
valor máximo de memória que foi usada
durante a execução
32. MOD_DEFLATE
• Comprime o arquivo com gzip antes de enviar (se o navegador
suportar)
•O custo de processamento normalmente é compensado com a
economia de banda
• Só compacte arquivos de texto (html, xml, css, js)
34. MOD_EXPIRES
• Digaao visitante até quando ele pode usar a versão atual de um
arquivo sem precisar acessar o servidor novamente
• Useo cache do cliente, economize requisições e dê a ele a
impressão de mais rapidez
• mod_expires coloca no cabeçalho HTTP a data de expiração
daquele arquivo
35. MOD_EXPIRES
$ a2enmod expires
No seu .htaccess ou configuração do site:
ExpiresActive On
ExpiresDefault "access plus 30 days"
ExpiresByType text/html "access plus 1 month 15 days
2 hours"
ExpiresByType image/gif "modification plus 5 hours 3
minutes"
36. DIRECTORYINDEX
• No Apache você pode configurar o DirectoryIndex que especifica
qual arquivo é o “index” de cada diretório
• Você pode especificar mais de um e o Apache segue a sequência
até achar o que exista:
<Directory /var/www>
DirectoryIndex index.html index.htm index.php
</Directory>
• Paraisso, é feita uma syscall para verificar a existência dos arquivos
a cada requisição
37. DIRECTORYINDEX
•O impacto é pequeno mas podemos evitar isso
• Configure o DirectoryIndex para ir direto para o arquivo correto
<Directory /var/www>
DirectoryIndex index.php
</Directory>
38. Use um servidor a
parte para
arquivos estáticos
http://static.example.com
41. APC
• PHPcompila os arquivos (JIT) e gera um código intermediário
(opcode) a cada execução
• Essa
compilação pode ser evitada, para isso é necessário fazer
cache do opcode
•A solução padrão é o APC
• Virá “built-in” no PHP6
42. APC
• Existem outras alternativas com o mesmo propósito
• XCache
• Zend Platform
43. APC
•A instalação é trivial, no Ubuntu basta executar:
# apt-get install php-apc
• Por padrão o cache do opcode já é habilitado
•O parâmetro apc.stat permite que o APC não cheque se o
arquivo foi alterado (aumentando ainda mais a performance), o
que é bom para sistemas em produção. Mas qualquer alteração
implica num restart do Apache.
45. MYSQL
• MySQL é o SGBD mais comumente utilizado com o PHP
• Foi
feito com foco em performance, mas com o tempo vem
ganhando funcionalidades voltadas para integridade relacional e
consistência dos dados
• Implementa um cache interno de queries
• Os principais engines são:
• MyISAM
• InnoDB
• Ambos usam índices organizados internamente em árvores B
• Qual escolher?
46. MYSQL - MYISAM
• Rápida para leitura
• Table-level locking
• Uma escrita trava todos os acessos paralelos à tabela
• INSERT DELAYED é não bloqueante e permite que seu PHP
continue executando enquanto a query fica na fila para ser
executada
• Índices FullText
47. MYSQL - MYISAM
• Menor consumo de memória e espaço em disco
• Utiliza recursos de cache do sistema operacional
48. MYSQL - INNODB
• Integridade relacional
• Chaves estrangeiras
• Row-level locking
• Na escrita, só é travado para acessos paralelos o registro que
está sendo escrito
• Maior consumo de memória e espaço em disco
• Utiliza implementação própria de cache
50. ÍNDICES
• Índices agilizam as buscas e tornam as escritas mais lentas
• Transformeem índice todas as colunas que são utilizadas como
parâmetro de consulta ou ordenação
• Remova o índice das colunas que não são utilizadas nessas
situações.
52. TIPOS DE DADOS
• Não armazene números em VARCHAR
• Não armazene datas em VARCHAR
• Se o campo tem tamanho fixo use CHAR
• Ex.: Uma senha em MD5 (32) ou SHA1 (41)
• Economiza espaço e facilita as comparações
54. CACHE
• Cacheé a solução mais comum para otimização de performance
em diversas áreas da computação
• Consiste
em armazenar uma informação que é mais acessada num
meio mais rápido do que a sua real origem.
• Por exemplo: Memória RAM serve de cache para o disco
55. CACHE
• Consulta
a dados que não se alteram com muita frequência
podem ser colocadas em cache. Por exemplo:
• Um site de notícias não precisa acessar o banco todas as vezes
que uma mesma notícia precisa ser exibida.
• Um site que agrega conteúdo de vários outros não precisa
consultar as APIs a cada acesso dos seus usuários. Ele pode
manter um cache local.
56. CACHE
• Iremos discutir a implementação de 4 tipos de cache:
• Smarty (Cache em disco)
• APC (Cache em memória)
• Memcache (Cache em memória em ambiente distribuído)
• Funky Caching (Cache em disco com a criação de arquivos
estáticos)
57. SMARTY
• Smarty é uma biblioteca muito popular de “template engine”
• Porém ela também oferece a funcionalidade de cache dos
templates já com as informações agregadas
• Gerandono disco um arquivo específico para cada registro
“cacheado”
• Você pode setar um TTL para o objeto em cache
58. SMARTY
http://smarty.net/manual/pt_BR/caching.php
<?php
require 'smarty/Smarty.class.php';
$id = (int) $_GET['id'];
$smarty = new Smarty();
$smarty->caching = 1;
if(!$smarty->is_cached('noticia.tpl',$id)) {
//Carrega do banco de dados
}
$smarty->display('noticia.tpl',$id);
59. APC
•O mesmo APC que faz cache do Opcode também faz cache de
objetos na memória
• apc.shm_size determina quanto de memória o APC pode usar
para armazenar objetos, quando esse espaço é ocupado, os que
foram usados a mais tempo são removidos (LRU)
• Você pode setar um TTL para o objeto em cache
60. APC
http://br.php.net/apc
<?php
$id = (int) $_GET['id'];
$cache_id = "noticia::$id";
if(!($noticia = apc_fetch($cache_id))) {
$noticia = new Noticia($id);
//Armazena o valor no cache em memória do APC
apc_store($cache_id, $noticia);
}
...
61. MEMCACHE
•O Memcache independe do PHP, é executado como um daemon
externo
• Conecta-se via sockets, e por isso não é indicado para grandes
objetos
• Utiliza também a política do LRU para remoção
• Você pode setar um TTL para o objeto em cache
63. MEMCACHE
• Memcachetambém pode ser utilizado como mecanismo para
armazenamento de dados de sessão.
• Isso
permite que se tenha vários servidores Web e independente
de qual servidor trate a requisição do usuário, pode-se acessar os
dados de sessão que estão no servidor Memcache, basta setar no
php.ini:
session.save_handler = memcache
session.save_path = "tcp://host_do_memcache:11211"
64. FUNKY CACHING
• FunkyCaching é uma técnica não muito elegante mais muito
eficiente
• Consiste em criar arquivos html estáticos sob demanda
• Usada no próprio site php.net
65. FUNKY CACHING
• No .htaccess ou outro arquivo de configuração do seu site no
Apache, especifique como página de erro 404 um script PHP que
é responsável por criar as páginas que não estão em cache.
• Por
exemplo, no diretório http://www.example.com/noticias/
poderíamos criar um .htacces com a regra:
ErrorDocument 404 /noticias/gera_cache.php
66. FUNKY CACHING
• No gera_noticias.php faríamos tratamento da URL que foi
requisitada e criaríamos o arquivo caso seja possível, por exemplo:
• http://www.example.com/noticias/1234.html indica que o
usuário quer acessar a notícia de id 1234
•O PHP cria esse arquivo e nos próximos acessos o html existirá
e o PHP não será mais chamado, pois não ocorrerá o erro 404.
67. FUNKY CACHING
<?php
$id = basename($_SERVER['REDIRECT_URL'], '.html');
/* Acessa a página dinâmica */
$html = file_get_contents(sprintf("http://www.example.com/
noticias.php?id=%d",$id));
/* O ideal é fazer algum tratamento de erros, para evitar a
criação de arquivos para ids inválidos */
/* Exibe o conteúdo */
header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
echo $html;
/* Salva o conteúdo em um arquivo .html */
file_put_contents(sprintf(dirname(__FILE__)."/%d.html", $id),
$html);
69. FIREBUG + YSLOW
• São plugins para o Mozilla Firefox
• Fazem análise para depuração (Firebug) e otimização (YSlow) de
toda a parte client-side
• YSlow foi desenvolvido pelo Yahoo Performance Team
70. FIREBUG - NET
Mostra o tempo de requisição, espera e download de cada
componente da página