Skip to content

Commit 046aa15

Browse files
daxtensstephenfin
authored andcommitted
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>
1 parent 98a2d05 commit 046aa15

File tree

5 files changed

+36
-24
lines changed

5 files changed

+36
-24
lines changed

patchwork/api/cover.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ class CoverLetterList(ListAPIView):
101101

102102
def get_queryset(self):
103103
return CoverLetter.objects.all()\
104-
.select_related('project', 'submitter', 'series__project')\
104+
.prefetch_related('series__project')\
105+
.select_related('project', 'submitter', 'series')\
105106
.defer('content', 'headers')
106107

107108

patchwork/api/filters.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ class TimestampMixin(BaseFilterSet):
164164

165165
class SeriesFilterSet(TimestampMixin, BaseFilterSet):
166166

167-
submitter = PersonFilter(queryset=Person.objects.all())
168-
project = ProjectFilter(queryset=Project.objects.all())
167+
submitter = PersonFilter(queryset=Person.objects.all(), distinct=False)
168+
project = ProjectFilter(queryset=Project.objects.all(), distinct=False)
169169

170170
class Meta:
171171
model = Series
@@ -174,12 +174,12 @@ class Meta:
174174

175175
class CoverLetterFilterSet(TimestampMixin, BaseFilterSet):
176176

177-
project = ProjectFilter(queryset=Project.objects.all())
177+
project = ProjectFilter(queryset=Project.objects.all(), distinct=False)
178178
# NOTE(stephenfin): We disable the select-based HTML widgets for these
179179
# filters as the resulting query is _huge_
180180
series = BaseFilter(queryset=Project.objects.all(),
181-
widget=MultipleHiddenInput)
182-
submitter = PersonFilter(queryset=Person.objects.all())
181+
widget=MultipleHiddenInput, distinct=False)
182+
submitter = PersonFilter(queryset=Person.objects.all(), distinct=False)
183183

184184
class Meta:
185185
model = CoverLetter
@@ -193,10 +193,10 @@ class PatchFilterSet(TimestampMixin, BaseFilterSet):
193193
# NOTE(stephenfin): We disable the select-based HTML widgets for these
194194
# filters as the resulting query is _huge_
195195
series = BaseFilter(queryset=Series.objects.all(),
196-
widget=MultipleHiddenInput)
197-
submitter = PersonFilter(queryset=Person.objects.all())
198-
delegate = UserFilter(queryset=User.objects.all())
199-
state = StateFilter(queryset=State.objects.all())
196+
widget=MultipleHiddenInput, distinct=False)
197+
submitter = PersonFilter(queryset=Person.objects.all(), distinct=False)
198+
delegate = UserFilter(queryset=User.objects.all(), distinct=False)
199+
state = StateFilter(queryset=State.objects.all(), distinct=False)
200200
hash = CharFilter(lookup_expr='iexact')
201201

202202
class Meta:
@@ -214,7 +214,7 @@ class Meta:
214214

215215
class CheckFilterSet(TimestampMixin, BaseFilterSet):
216216

217-
user = UserFilter(queryset=User.objects.all())
217+
user = UserFilter(queryset=User.objects.all(), distinct=False)
218218

219219
class Meta:
220220
model = Check
@@ -227,13 +227,17 @@ class EventFilterSet(TimestampMixin, BaseFilterSet):
227227
# filters as the resulting query is _huge_
228228
# TODO(stephenfin): We should really use an AJAX widget of some form here
229229
project = ProjectFilter(queryset=Project.objects.all(),
230-
widget=MultipleHiddenInput)
230+
widget=MultipleHiddenInput,
231+
distinct=False)
231232
series = BaseFilter(queryset=Series.objects.all(),
232-
widget=MultipleHiddenInput)
233+
widget=MultipleHiddenInput,
234+
distinct=False)
233235
patch = BaseFilter(queryset=Patch.objects.all(),
234-
widget=MultipleHiddenInput)
236+
widget=MultipleHiddenInput,
237+
distinct=False)
235238
cover = BaseFilter(queryset=CoverLetter.objects.all(),
236-
widget=MultipleHiddenInput)
239+
widget=MultipleHiddenInput,
240+
distinct=False)
237241

238242
class Meta:
239243
model = Event
@@ -245,8 +249,8 @@ class Meta:
245249

246250
class BundleFilterSet(BaseFilterSet):
247251

248-
project = ProjectFilter(queryset=Project.objects.all())
249-
owner = UserFilter(queryset=User.objects.all())
252+
project = ProjectFilter(queryset=Project.objects.all(), distinct=False)
253+
owner = UserFilter(queryset=User.objects.all(), distinct=False)
250254

251255
class Meta:
252256
model = Bundle

patchwork/api/series.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ class SeriesMixin(object):
5656

5757
def get_queryset(self):
5858
return Series.objects.all()\
59-
.prefetch_related('patches__project',)\
60-
.select_related('submitter', 'cover_letter__project', 'project')
59+
.prefetch_related('patches__project', 'cover_letter__project')\
60+
.select_related('submitter', 'project')
6161

6262

6363
class SeriesList(SeriesMixin, ListAPIView):

patchwork/tests/api/test_cover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def test_list_bug_335(self):
127127
series = create_series()
128128
create_covers(5, series=series)
129129

130-
with self.assertNumQueries(2):
130+
with self.assertNumQueries(3):
131131
self.client.get(self.api_url())
132132

133133
@utils.store_samples('cover-detail')

patchwork/tests/api/test_series.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,17 @@ def test_list_version_1_0(self):
139139
self.assertNotIn('web_url', resp.data[0]['patches'][0])
140140

141141
def test_list_bug_335(self):
142-
"""Ensure we retrieve the embedded cover letter project once."""
143-
self._create_series()
144-
145-
with self.assertNumQueries(4):
142+
"""Ensure we retrieve the embedded cover letter project in O(1)."""
143+
project_obj = create_project(linkname='myproject')
144+
person_obj = create_person(email='test@example.com')
145+
for i in range(10):
146+
series_obj = create_series(
147+
project=project_obj, submitter=person_obj,
148+
)
149+
create_cover(series=series_obj)
150+
create_patch(series=series_obj)
151+
152+
with self.assertNumQueries(6):
146153
self.client.get(self.api_url())
147154

148155
@utils.store_samples('series-detail')

0 commit comments

Comments
 (0)