diff options
author | Daniel Axtens <dja@axtens.net> | 2020-03-18 00:59:15 +1100 |
---|---|---|
committer | Stephen Finucane <stephen@that.guru> | 2020-03-19 11:51:54 +0000 |
commit | 046aa155c3bf827691bab9e1df8916c969a30d54 (patch) | |
tree | 03cca9705cd81d5ee631d993954cd388b184ecce | |
parent | 98a2d051372dcedb889c4cb94ebd8ed7b399b522 (diff) | |
download | patchwork-046aa155c3bf827691bab9e1df8916c969a30d54.tar patchwork-046aa155c3bf827691bab9e1df8916c969a30d54.tar.gz |
REST: extend performance improvements to other parts of the API
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 <dja@axtens.net>
Reviewed-by: Stephen Finucane <stephen@that.guru>
-rw-r--r-- | patchwork/api/cover.py | 3 | ||||
-rw-r--r-- | patchwork/api/filters.py | 36 | ||||
-rw-r--r-- | patchwork/api/series.py | 4 | ||||
-rw-r--r-- | patchwork/tests/api/test_cover.py | 2 | ||||
-rw-r--r-- | patchwork/tests/api/test_series.py | 15 |
5 files changed, 36 insertions, 24 deletions
diff --git a/patchwork/api/cover.py b/patchwork/api/cover.py index 9e86d47..c0c27fe 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 a3b6f03..f7b6a6f 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 df28f95..e4cffaa 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 16cc0cd..5eeb190 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 8751871..491dd61 100644 --- a/patchwork/tests/api/test_series.py +++ b/patchwork/tests/api/test_series.py @@ -139,10 +139,17 @@ 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() - - with self.assertNumQueries(4): + """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(6): self.client.get(self.api_url()) @utils.store_samples('series-detail') |