Contagem de consultas: teste básico de desempenho do Django

Olá a todos. Preparamos uma tradução de outro material útil para os alunos do curso "Web-developer in Python" , que começou ontem.





Você pode ouvir sobre métodos de teste, como TDD, e como testar a lógica de negócios de um aplicativo. No entanto, testar o desempenho do aplicativo é uma tarefa completamente diferente. Existem muitas maneiras diferentes, mas a abordagem mais comum é criar um ambiente no qual você possa realizar um ataque DDoS ao seu aplicativo e observar seu comportamento. Este é um tópico muito interessante, mas não é sobre isso que quero falar hoje. Hoje, veremos um teste mais simples, que você pode fazer usando os testes de unidade padrão do Django: isto é, testar o número de vezes que seu aplicativo acessa o banco de dados.

Testar isso é muito simples e esse é exatamente o aspecto que pode prejudicar o desempenho do aplicativo nos estágios iniciais. Esse aspecto é o primeiro a ser testado quando algo começa a funcionar lentamente. A boa notícia é que há apenas uma coisa que você precisa saber para escrever testes desse tipo: o método assertNumQueries , e é muito fácil de usar. Aqui está um exemplo:

from django.test import TestCase, Client
from django.urls import reverse
from trucks.models import Truck

class TrucksTestCase(TestCase):
    def test_list_trucks_view_performance(self):
        client = Client()

        Truck.objects.create(...)

        with self.assertNumQueries(6):
            response = client.get(reverse("trucks:list_trucks"))

        self.assertEqual(response.context["trucks_list"], 1)

O código acima afirma que, durante a visualização, o "trucks:list_trucks"aplicativo acessará o banco de dados apenas 6 vezes. Mas há outra coisa, observe que, antes de começar, primeiro criamos um novo objeto Trucke depois dizemos que trucks_listhá pelo menos um objeto nos dados de contexto da exibição . Nesse tipo de teste, isso é importante porque você precisa de uma garantia de que não está testando em um conjunto de dados vazio. É importante entender que apenas instanciar uma classe Trucknão é suficiente. Você precisa verificar se foi incluído no contexto. Talvez você esteja filtrando a lista de caminhões, portanto, é provável que sua instância Trucknão seja incluída no resultado.

Depois de tudo isso, já fizemos um progresso significativo, mas há outro passo importante que é fácil esquecer. Se queremos que nossas visualizações sejam dimensionadas, devemos garantir que o desempenho não diminua à medida que o número de itens retornados aumenta. No final, ainda temos um problema de desempenho se recorrermos ao banco de dados não seis vezes para obter um item, mas 106 se tivermos 100 itens. Precisamos de um número constante de chamadas ao banco de dados, o que não dependerá do número de itens retornados. Felizmente, esse problema também é resolvido com muita simplicidade, precisamos adicionar mais um (ou vários) elementos ao banco de dados e contar novamente o número de ocorrências. É assim que o teste ficará na versão final:

from django.test import TestCase, Client
from django.urls import reverse
from trucks.models import Truck

class TrucksTestCase(TestCase):
    def test_list_trucks_view_performance(self):
        client = Client()

        Truck.objects.create(...)

        with self.assertNumQueries(6):
            response = client.get(reverse("trucks:list_trucks"))

        self.assertEqual(response.context["trucks_list"], 1)

        Truck.objects.create(...)

        with self.assertNumQueries(6):
            response = client.get(reverse("trucks:list_trucks"))

        self.assertEqual(response.context["trucks_list"], 2)

Observe que, novamente, verificamos o número de itens retornados no contexto, mas na segunda execução esperamos 2 caminhões ( Truck). A razão para esse comportamento é semelhante ao primeiro caso.

Garantir um número constante de chamadas ao banco de dados ao adicionar novos dados é mais prioritário do que garantir um pequeno número de chamadas em geral.

A última coisa a fazer é garantir que seus dados estejam o mais hidratados possível. Isso significa que você precisa criar dados relacionados que serão usados ​​durante o processamento da sua visualização. Caso contrário, existe o risco de seu aplicativo acessar o banco de dados com mais frequência na produção do que no teste (embora possa ter êxito). Em nosso exemplo, precisávamos criar TruckDriveruma empresa para nossosTruck.

from trucks.models import Truck, TruckDriver
...
        truck = Truck.objects.create(...)
        TruckDriver.objects.create(name="Alex", truck=truck)

Se o número de chamadas ao banco de dados não for mais constante após a execução das etapas descritas acima, procure mais informações sobre os métodos select_related e prefetch_related .

Isso é tudo por hoje, espero que a partir de agora você comece a verificar o número de consultas que seu aplicativo possui para o banco de dados no início do projeto. Isso não levará muito tempo, mas evitará problemas que possam surgir com o aumento do número de usuários do seu aplicativo.

A propósito, você ainda pode pegar o curso . Até logo.

All Articles