From patchwork Tue Mar 17 13:59:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Axtens X-Patchwork-Id: 1256496 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hbms4JjWz9sSq for ; Wed, 18 Mar 2020 01:54:53 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=axtens.net header.i=@axtens.net header.a=rsa-sha256 header.s=google header.b=QQWau26+; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 48hbms1nMfzDqQf for ; Wed, 18 Mar 2020 01:54:53 +1100 (AEDT) X-Original-To: patchwork@lists.ozlabs.org Delivered-To: patchwork@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=axtens.net (client-ip=2607:f8b0:4864:20::42c; helo=mail-pf1-x42c.google.com; envelope-from=dja@axtens.net; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=axtens.net Authentication-Results: lists.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=axtens.net header.i=@axtens.net header.a=rsa-sha256 header.s=google header.b=QQWau26+; dkim-atps=neutral Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 48hZY72s9dzDqgB for ; Wed, 18 Mar 2020 00:59:39 +1100 (AEDT) Received: by mail-pf1-x42c.google.com with SMTP id l184so11985728pfl.7 for ; Tue, 17 Mar 2020 06:59:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axtens.net; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Sww7TPUKMbfVepgfl5meug4e9nIZbVV1hBE6hAC8UE4=; b=QQWau26+AhiKfrTSNMM5VaYql4lUBr7lR9Ncc4odaLHvga7VnOF3mlWuk94gnBGH/w BMXNM7GDpMFdQgXMx8or9lDDYFGxoB6JtQbOr98ucYc72qNGKjqXMwYYT153fYv8zdxr b+jNSXAkonL+c6Sa8vAP1Nd+I9SxiEDoR+5jo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Sww7TPUKMbfVepgfl5meug4e9nIZbVV1hBE6hAC8UE4=; b=ZSa3lOMHWwOdNat++3sNpqv+5gVQyZi22a0f3NQhId+4bRMuSbsaPhx+U2jsRG+GCj yk5uSkMwe1uTSegu3wpaQtCeL3OWoEMDB72PtPQdvXiAGjXNb5iC+2VnNmHSjmJVMhrn 4BYNTxdOg7qCE/AVqp4neTnCoN9nplYmw2QYLioe1ypwJB7vaUK0CXAKuHwgDlU1c7ft pjgFr4YsFCuq2btFZtXNAlD9wyeMhmUaT5f9KPKjfrYppERCl9OCCTXM0cyNSm1zKf3f c8QIwv+y8YOgfBjc0AsYNMCzM/FGk1fS+tl07tJaWeuh0SuMAi8IYgQdU/hBBqVoECmQ AUug== X-Gm-Message-State: ANhLgQ1U8c3G1GglVR84nvJHEa1iSuTiMUL1Yce4OdhbI6edzJLSiXDm Rzb/TrYCoYTmrPOsVUkPl+wKMoqmQjI= X-Google-Smtp-Source: ADFU+vuu0Z3MuY5MVU1eBjAZusqVRYxzVWUL4FUHcZ+hahetfOuX5M0WWdi8fMYVOX+274RCtupaCA== X-Received: by 2002:a63:5549:: with SMTP id f9mr5284247pgm.118.1584453576204; Tue, 17 Mar 2020 06:59:36 -0700 (PDT) Received: from localhost (2001-44b8-111e-5c00-11e1-e7cb-3c10-05d6.static.ipv6.internode.on.net. [2001:44b8:111e:5c00:11e1:e7cb:3c10:5d6]) by smtp.gmail.com with ESMTPSA id g6sm2955517pjv.13.2020.03.17.06.59.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Mar 2020 06:59:35 -0700 (PDT) From: Daniel Axtens To: patchwork@lists.ozlabs.org Subject: [PATCH 3/4] REST: extend performance improvements to other parts of the API Date: Wed, 18 Mar 2020 00:59:15 +1100 Message-Id: <20200317135916.13691-4-dja@axtens.net> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200317135916.13691-1-dja@axtens.net> References: <20200317135916.13691-1-dja@axtens.net> MIME-Version: 1.0 X-BeenThere: patchwork@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Patchwork development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Patchwork" We can trivially extend what we've just done to other parts of the API. I haven't done much by way of benchmark but we're seeing multiple 'x's pretty much across the board when filtering. Signed-off-by: Daniel Axtens --- patchwork/api/cover.py | 3 ++- patchwork/api/filters.py | 36 +++++++++++++++++------------- patchwork/api/series.py | 4 ++-- patchwork/tests/api/test_cover.py | 2 +- patchwork/tests/api/test_series.py | 12 +++++++--- 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/patchwork/api/cover.py b/patchwork/api/cover.py index 9e86d47e00e5..c0c27fe8ece4 100644 --- a/patchwork/api/cover.py +++ b/patchwork/api/cover.py @@ -101,7 +101,8 @@ class CoverLetterList(ListAPIView): def get_queryset(self): return CoverLetter.objects.all()\ - .select_related('project', 'submitter', 'series__project')\ + .prefetch_related('series__project')\ + .select_related('project', 'submitter', 'series')\ .defer('content', 'headers') diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py index a3b6f03c6ccd..f7b6a6f66f22 100644 --- a/patchwork/api/filters.py +++ b/patchwork/api/filters.py @@ -164,8 +164,8 @@ class TimestampMixin(BaseFilterSet): class SeriesFilterSet(TimestampMixin, BaseFilterSet): - submitter = PersonFilter(queryset=Person.objects.all()) - project = ProjectFilter(queryset=Project.objects.all()) + submitter = PersonFilter(queryset=Person.objects.all(), distinct=False) + project = ProjectFilter(queryset=Project.objects.all(), distinct=False) class Meta: model = Series @@ -174,12 +174,12 @@ class SeriesFilterSet(TimestampMixin, BaseFilterSet): class CoverLetterFilterSet(TimestampMixin, BaseFilterSet): - project = ProjectFilter(queryset=Project.objects.all()) + project = ProjectFilter(queryset=Project.objects.all(), distinct=False) # NOTE(stephenfin): We disable the select-based HTML widgets for these # filters as the resulting query is _huge_ series = BaseFilter(queryset=Project.objects.all(), - widget=MultipleHiddenInput) - submitter = PersonFilter(queryset=Person.objects.all()) + widget=MultipleHiddenInput, distinct=False) + submitter = PersonFilter(queryset=Person.objects.all(), distinct=False) class Meta: model = CoverLetter @@ -193,10 +193,10 @@ class PatchFilterSet(TimestampMixin, BaseFilterSet): # NOTE(stephenfin): We disable the select-based HTML widgets for these # filters as the resulting query is _huge_ series = BaseFilter(queryset=Series.objects.all(), - widget=MultipleHiddenInput) - submitter = PersonFilter(queryset=Person.objects.all()) - delegate = UserFilter(queryset=User.objects.all()) - state = StateFilter(queryset=State.objects.all()) + widget=MultipleHiddenInput, distinct=False) + submitter = PersonFilter(queryset=Person.objects.all(), distinct=False) + delegate = UserFilter(queryset=User.objects.all(), distinct=False) + state = StateFilter(queryset=State.objects.all(), distinct=False) hash = CharFilter(lookup_expr='iexact') class Meta: @@ -214,7 +214,7 @@ class PatchFilterSet(TimestampMixin, BaseFilterSet): class CheckFilterSet(TimestampMixin, BaseFilterSet): - user = UserFilter(queryset=User.objects.all()) + user = UserFilter(queryset=User.objects.all(), distinct=False) class Meta: model = Check @@ -227,13 +227,17 @@ class EventFilterSet(TimestampMixin, BaseFilterSet): # filters as the resulting query is _huge_ # TODO(stephenfin): We should really use an AJAX widget of some form here project = ProjectFilter(queryset=Project.objects.all(), - widget=MultipleHiddenInput) + widget=MultipleHiddenInput, + distinct=False) series = BaseFilter(queryset=Series.objects.all(), - widget=MultipleHiddenInput) + widget=MultipleHiddenInput, + distinct=False) patch = BaseFilter(queryset=Patch.objects.all(), - widget=MultipleHiddenInput) + widget=MultipleHiddenInput, + distinct=False) cover = BaseFilter(queryset=CoverLetter.objects.all(), - widget=MultipleHiddenInput) + widget=MultipleHiddenInput, + distinct=False) class Meta: model = Event @@ -245,8 +249,8 @@ class EventFilterSet(TimestampMixin, BaseFilterSet): class BundleFilterSet(BaseFilterSet): - project = ProjectFilter(queryset=Project.objects.all()) - owner = UserFilter(queryset=User.objects.all()) + project = ProjectFilter(queryset=Project.objects.all(), distinct=False) + owner = UserFilter(queryset=User.objects.all(), distinct=False) class Meta: model = Bundle diff --git a/patchwork/api/series.py b/patchwork/api/series.py index df28f95dab1b..e4cffaa3b384 100644 --- a/patchwork/api/series.py +++ b/patchwork/api/series.py @@ -56,8 +56,8 @@ class SeriesMixin(object): def get_queryset(self): return Series.objects.all()\ - .prefetch_related('patches__project',)\ - .select_related('submitter', 'cover_letter__project', 'project') + .prefetch_related('patches__project', 'cover_letter__project')\ + .select_related('submitter', 'project') class SeriesList(SeriesMixin, ListAPIView): diff --git a/patchwork/tests/api/test_cover.py b/patchwork/tests/api/test_cover.py index 16cc0cd96f26..5eeb1902e1d1 100644 --- a/patchwork/tests/api/test_cover.py +++ b/patchwork/tests/api/test_cover.py @@ -127,7 +127,7 @@ class TestCoverLetterAPI(utils.APITestCase): series = create_series() create_covers(5, series=series) - with self.assertNumQueries(2): + with self.assertNumQueries(3): self.client.get(self.api_url()) @utils.store_samples('cover-detail') diff --git a/patchwork/tests/api/test_series.py b/patchwork/tests/api/test_series.py index 87518719b887..fd06a1e06047 100644 --- a/patchwork/tests/api/test_series.py +++ b/patchwork/tests/api/test_series.py @@ -139,10 +139,16 @@ class TestSeriesAPI(utils.APITestCase): self.assertNotIn('web_url', resp.data[0]['patches'][0]) def test_list_bug_335(self): - """Ensure we retrieve the embedded cover letter project once.""" - self._create_series() + """Ensure we retrieve the embedded cover letter project in O(1).""" + project_obj = create_project(linkname='myproject') + person_obj = create_person(email='test@example.com') + for i in range(10): + series_obj = create_series(project=project_obj, + submitter=person_obj) + create_cover(series=series_obj) + create_patch(series=series_obj) - with self.assertNumQueries(4): + with self.assertNumQueries(6): self.client.get(self.api_url()) @utils.store_samples('series-detail')