Skip to content

Ajuste de desempenho ​

Muitos fatores afetam o desempenho da sua aplicação. Alguns são do ambiente, outros estão ligados ao seu código, e outros ao próprio Yii. Nesta seção, listamos a maioria desses fatores e explicamos como você pode melhorar o desempenho da aplicação ajustando cada um deles.

Otimizando o ambiente PHP ​

Um ambiente PHP bem configurado é importante. Para obter o máximo de desempenho:

  • Use a versão estável mais recente do PHP. Versões principais do PHP podem trazer ganhos de desempenho significativos.
  • Ative o cache de bytecode com o Opcache. O cache de bytecode evita o tempo gasto para analisar e incluir os scripts PHP a cada requisição.
  • Ajuste o cache do realpath().
  • Garanta que o XDebug não esteja instalado no ambiente de produção.
  • Experimente o preload do PHP 7.

Otimizando o seu código ​

Além da configuração do ambiente, há otimizações no nível do código que podem melhorar o desempenho da aplicação:

As otimizações acima só trazem um ganho de desempenho significativo se o código em questão for executado com frequência. Normalmente é o caso de loops grandes ou de processamento em lote.

Usando técnicas de cache ​

Você pode usar várias técnicas de cache para melhorar bastante o desempenho da aplicação. Por exemplo, se a sua aplicação permite que os usuários digitem texto em Markdown, considere guardar em cache o conteúdo Markdown já processado, para não processar o mesmo texto repetidamente a cada requisição. Consulte a seção de Cache para conhecer o suporte a cache oferecido pelo Yii.

Otimizando o armazenamento de sessões ​

Por padrão, os dados de sessão são guardados em arquivos. A implementação trava o arquivo desde a abertura da sessão até o momento em que ela é fechada, seja por $session->close() ou no fim da requisição. Enquanto o arquivo de sessão está travado, todas as outras requisições que tentam usar a mesma sessão ficam bloqueadas, esperando a requisição inicial liberar o arquivo de sessão. Isso serve para desenvolvimento e, provavelmente, para projetos pequenos. Mas quando se trata de lidar com muitas requisições concorrentes, é melhor usar um armazenamento mais sofisticado, como o Redis.

Isso pode ser feito configurando o PHP via php.ini ou implementando a SessionHandlerInterface e configurando o serviço de sessão assim:

php
\Yiisoft\Session\SessionInterface::class => [
    'class' => \Yiisoft\Session\Session::class,
    '__construct()' => [[], $myCustomSessionHandler],
],

Otimizando bancos de dados ​

Executar consultas e buscar dados no banco de dados costuma ser o principal gargalo de desempenho de uma aplicação web. Embora técnicas de cache de dados possam amenizar o impacto, elas não resolvem totalmente o problema. Quando o banco de dados tem uma quantidade enorme de dados e os dados em cache ficam inválidos, buscar os dados mais recentes pode ficar caro demais sem um bom projeto de banco de dados e de consultas.

Uma técnica geral para melhorar o desempenho das consultas é criar índices nas colunas das tabelas usadas em filtros. Por exemplo, se você precisa buscar o registro de um usuário pelo username, crie um índice em username. Note que, embora a indexação possa deixar as consultas SELECT muito mais rápidas, ela deixa as consultas INSERT, UPDATE e DELETE mais lentas.

Para consultas complexas, é recomendável criar views no banco de dados para economizar o tempo de análise e preparação da consulta.

Por último, mas não menos importante, use LIMIT nas suas consultas SELECT. Isso evita buscar uma quantidade excessiva de dados no banco e esgotar a memória alocada para o PHP.

Otimizando o autoloader do Composer ​

Como o autoloader do Composer é usado para incluir a maioria dos arquivos de classes de terceiros, considere otimizá-lo executando o seguinte comando:

composer dumpautoload -o

Além disso, você pode considerar o uso de class maps autoritativos e do cache APCu. Note que essas duas otimizações podem ou não ser adequadas ao seu caso.

Processando dados offline ​

Quando uma requisição envolve operações que consomem muitos recursos, pense em formas de executá-las em modo offline, sem fazer os usuários esperarem que terminem.

Há dois métodos para processar dados offline: pull e push.

No método pull, sempre que uma requisição envolve alguma operação complexa, você cria uma tarefa e a salva num armazenamento persistente, como um banco de dados. Depois, usa um processo separado (como um cron job) para buscar as tarefas e processá-las. Esse método é simples de implementar, mas tem algumas desvantagens. Por exemplo, o processo de tarefas precisa consultar periodicamente o armazenamento de tarefas. Se a frequência for baixa demais, as tarefas podem ser processadas com muito atraso; se for alta demais, gera muito overhead.

No método push, você usa uma fila de mensagens (por exemplo, RabbitMQ, ActiveMQ, Amazon SQS etc.) para gerenciar as tarefas. Sempre que uma nova tarefa entra na fila, ela inicia ou notifica o processo responsável, que dispara o processamento da tarefa.

Usando preload ​

A partir do PHP 7.4.0, o PHP pode ser configurado para pré-carregar scripts no opcache quando o engine inicia. Saiba mais na documentação e na RFC correspondente.

Note que o equilíbrio ideal entre desempenho e memória pode variar conforme a aplicação. "Pré-carregar tudo" pode ser a estratégia mais fácil, mas não necessariamente a melhor.

Por exemplo, fizemos um benchmark simples do template de aplicação yiisoft/app: sem preload e com preload de todo o class map do Composer.

Benchmarks de preload ​

O benchmark do template de aplicação inclui a configuração das classes para as dependências injetadas no script de bootstrap.

Nas duas variantes, foi usado o ApacheBench com os seguintes parâmetros de execução:

shell
ab -n 1000 -c 10 -t 10

Além disso, o modo debug estava desativado. Também foi usado um autoloader otimizado do Composer, sem as dependências de desenvolvimento:

shell
composer install --optimize-autoloader --no-dev

Com o preload ativado, foi usado todo o class map do Composer (825 arquivos):

php
$files = require 'vendor/composer/autoload_classmap.php';

foreach (array_unique($files) as $file) {
    opcache_compile_file($file);
}

Resultados dos testes ​

BenchmarkArquivos pré-carregadosMemória do Opcache usadaMemória usada por requisiçãoTempo por requisiçãoRequisições por segundo
Sem preload012.32 mb1.71 mb27.63 ms36.55 rq/s
Com preload82517.86 mb1.82 mb26.21 ms38.42 rq/s

Como você pode ver, os resultados não são muito diferentes, já que este é apenas um template de aplicação limpo, com poucas classes. Mais discussões sobre preload, incluindo benchmarks, estão na issue do Composer.

Profiling de desempenho ​

Faça o profiling do seu código para encontrar os gargalos de desempenho e tomar as medidas adequadas. As seguintes ferramentas de profiling podem ser úteis: