Skip to content

Commit 68f4a61

Browse files
Backend: Optimize create_or_update_github_challenge function to prefetch challenge_phase_splits, reducing N+1 query issues during updates; add unit test to verify performance improvements. (#5001)
1 parent 2beef64 commit 68f4a61

File tree

13 files changed

+337
-29
lines changed

13 files changed

+337
-29
lines changed

apps/challenges/views.py

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4561,20 +4561,44 @@ def create_or_update_github_challenge(request, challenge_host_team_pk):
45614561
error_messages, status=status.HTTP_400_BAD_REQUEST
45624562
)
45634563

4564+
# Prefetch all challenge_phase_splits for this challenge to avoid
4565+
# N+1 queries in the leaderboard, dataset_split, and
4566+
# challenge_phase_split update loops.
4567+
all_challenge_phase_splits = list(
4568+
ChallengePhaseSplit.objects.filter(
4569+
challenge_phase__challenge__pk=challenge.pk
4570+
).select_related(
4571+
"challenge_phase", "dataset_split", "leaderboard"
4572+
)
4573+
)
4574+
cps_by_leaderboard_config_id = {
4575+
cps.leaderboard.config_id: cps
4576+
for cps in all_challenge_phase_splits
4577+
if cps.leaderboard.config_id is not None
4578+
}
4579+
cps_by_dataset_split_config_id = {
4580+
cps.dataset_split.config_id: cps
4581+
for cps in all_challenge_phase_splits
4582+
if cps.dataset_split.config_id is not None
4583+
}
4584+
cps_by_phase_split_leaderboard = {
4585+
(
4586+
cps.challenge_phase_id,
4587+
cps.dataset_split_id,
4588+
cps.leaderboard_id,
4589+
): cps
4590+
for cps in all_challenge_phase_splits
4591+
}
4592+
45644593
# Updating Leaderboard object
45654594
leaderboard_ids = {}
45664595
yaml_file_data_of_leaderboard = yaml_file_data["leaderboard"]
45674596
for data in yaml_file_data_of_leaderboard:
4568-
challenge_phase_split_qs = (
4569-
ChallengePhaseSplit.objects.filter(
4570-
challenge_phase__challenge__pk=challenge.pk,
4571-
leaderboard__config_id=data["config_id"],
4572-
)
4597+
leaderboard_config_id = data.get("config_id", data["id"])
4598+
challenge_phase_split = cps_by_leaderboard_config_id.get(
4599+
leaderboard_config_id
45734600
)
4574-
if challenge_phase_split_qs:
4575-
challenge_phase_split = (
4576-
challenge_phase_split_qs.first()
4577-
)
4601+
if challenge_phase_split is not None:
45784602
leaderboard = challenge_phase_split.leaderboard
45794603
serializer = LeaderboardSerializer(
45804604
leaderboard,
@@ -4672,16 +4696,10 @@ def create_or_update_github_challenge(request, challenge_host_team_pk):
46724696
]
46734697
dataset_split_ids = {}
46744698
for data in yaml_file_data_of_dataset_split:
4675-
challenge_phase_split_qs = (
4676-
ChallengePhaseSplit.objects.filter(
4677-
challenge_phase__challenge__pk=challenge.pk,
4678-
dataset_split__config_id=data["id"],
4679-
)
4699+
challenge_phase_split = cps_by_dataset_split_config_id.get(
4700+
data["id"]
46804701
)
4681-
if challenge_phase_split_qs:
4682-
challenge_phase_split = (
4683-
challenge_phase_split_qs.first()
4684-
)
4702+
if challenge_phase_split is not None:
46854703
dataset_split = challenge_phase_split.dataset_split
46864704
serializer = DatasetSplitSerializer(
46874705
dataset_split,
@@ -4770,17 +4788,10 @@ def create_or_update_github_challenge(request, challenge_host_team_pk):
47704788
"leaderboard_decimal_precision": leaderboard_decimal_precision,
47714789
}
47724790

4773-
challenge_phase_split_qs = (
4774-
ChallengePhaseSplit.objects.filter(
4775-
challenge_phase__pk=challenge_phase,
4776-
dataset_split__pk=dataset_split,
4777-
leaderboard__pk=leaderboard,
4778-
)
4791+
challenge_phase_split = cps_by_phase_split_leaderboard.get(
4792+
(challenge_phase, dataset_split, leaderboard)
47794793
)
4780-
if challenge_phase_split_qs:
4781-
challenge_phase_split = (
4782-
challenge_phase_split_qs.first()
4783-
)
4794+
if challenge_phase_split is not None:
47844795
serializer = ZipChallengePhaseSplitSerializer(
47854796
challenge_phase_split, data=data
47864797
)
@@ -4791,7 +4802,11 @@ def create_or_update_github_challenge(request, challenge_host_team_pk):
47914802
if serializer.is_valid():
47924803
serializer.save()
47934804
else:
4794-
error_messages = f"challenge phase split update (phase:{data['challenge_phase_id']}, leaderboard:{data['leaderboard_id']}, dataset split: {data['dataset_split_id']}):{str(serializer.errors)}"
4805+
error_messages = (
4806+
f"challenge phase split update "
4807+
f"(phase:{challenge_phase}, leaderboard:{leaderboard}, "
4808+
f"dataset split: {dataset_split}):{str(serializer.errors)}"
4809+
)
47954810
raise RuntimeError()
47964811

47974812
response_data = {
22.1 KB
Binary file not shown.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
title: Challenge Title
2+
short_description: Short description of the challenge (preferably 140 characters)
3+
description: description.html
4+
evaluation_details: evaluation_details.html
5+
terms_and_conditions: terms_and_conditions.html
6+
image : logo.png
7+
submission_guidelines: submission_guidelines.html
8+
evaluation_script: evaluation_script.zip
9+
start_date: 2017-06-09 20:00:00
10+
end_date: 2017-06-19 20:00:00
11+
12+
leaderboard:
13+
- id: 1
14+
schema: {"labels": ["yes/no", "number", "others", "overall"], "default_order_by": "overall"}
15+
- id: 2
16+
schema: {"labels": ["metric_a", "metric_b"], "default_order_by": "metric_a"}
17+
18+
challenge_phases:
19+
- id: 1
20+
name: Challenge Phase 1
21+
description: challenge_phase_description.html
22+
leaderboard_public: True
23+
is_public: True
24+
start_date: 2017-06-09 20:00:00
25+
end_date: 2017-06-19 20:00:00
26+
test_annotation_file: test_annotation.txt
27+
codename: phase1
28+
max_submissions_per_day: 100
29+
max_submissions: 1000
30+
max_submissions_per_month: 1000
31+
- id: 2
32+
name: Challenge Phase 2
33+
description: challenge_phase_description.html
34+
leaderboard_public: True
35+
is_public: True
36+
start_date: 2017-06-09 20:00:00
37+
end_date: 2017-06-19 20:00:00
38+
test_annotation_file: test_annotation.txt
39+
codename: phase2
40+
max_submissions_per_day: 100
41+
max_submissions: 1000
42+
max_submissions_per_month: 1000
43+
44+
dataset_splits:
45+
- id: 1
46+
name: Name of the dataset split
47+
codename: codename of dataset split
48+
- id: 2
49+
name: Name of the dataset split 2
50+
codename: codename of dataset split 2
51+
52+
challenge_phase_splits:
53+
- challenge_phase_id: 1
54+
leaderboard_id: 1
55+
dataset_split_id: 1
56+
visibility: 3
57+
leaderboard_decimal_precision: 2
58+
is_leaderboard_order_descending: True
59+
- challenge_phase_id: 1
60+
leaderboard_id: 2
61+
dataset_split_id: 1
62+
visibility: 3
63+
leaderboard_decimal_precision: 2
64+
is_leaderboard_order_descending: True
65+
- challenge_phase_id: 2
66+
leaderboard_id: 1
67+
dataset_split_id: 1
68+
visibility: 3
69+
leaderboard_decimal_precision: 2
70+
is_leaderboard_order_descending: True
71+
- challenge_phase_id: 2
72+
leaderboard_id: 2
73+
dataset_split_id: 2
74+
visibility: 3
75+
leaderboard_decimal_precision: 2
76+
is_leaderboard_order_descending: True
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="row">
2+
<p><span style="font-weight: 400;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span></p>
3+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="row">
2+
<p><span style="font-weight: 400;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span></p>
3+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="row">
2+
<p><span style="font-weight: 400;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span></p>
3+
</div>
1.14 KB
Binary file not shown.
17.9 KB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="row">
2+
<p><span style="font-weight: 400;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span></p>
3+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="row">
2+
<p><span style="font-weight: 400;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</span></p>
3+
</div>

0 commit comments

Comments
 (0)