Skip to content

Commit e6406f8

Browse files
Drastically speed up creating rejudgings by using direct queries
On my laptop creating a rejudging for the whole of WF46 went from 807 seconds to 16 seconds, a 50x improvement.
1 parent 274d36a commit e6406f8

File tree

2 files changed

+66
-43
lines changed

2 files changed

+66
-43
lines changed

webapp/src/Service/DOMJudgeService.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,14 +1202,17 @@ public function maybeCreateJudgeTasks(Judging $judging, int $priority = JudgeTas
12021202
// - the new submission would get X+5+60 (since there's only one of their submissions still to be worked on),
12031203
// but we want to judge submissions of this team in order, so we take the current max (X+120) and add 1.
12041204
$teamPriority = (int)(max($result['max']+1, $submission->getSubmittime() + 60*$result['count']));
1205-
$queueTask = new QueueTask();
1206-
$queueTask->setJudging($judging)
1207-
->setPriority($priority)
1208-
->setTeam($team)
1209-
->setTeamPriority($teamPriority)
1210-
->setStartTime(null);
1211-
$this->em->persist($queueTask);
1212-
$this->em->flush();
1205+
// Use a direct query to speed things up
1206+
$this->em->getConnection()->executeQuery(
1207+
'INSERT INTO queuetask (judgingid, priority, teamid, teampriority, starttime)
1208+
VALUES (:judgingid, :priority, :teamid, :teampriority, null)',
1209+
[
1210+
'judgingid' => $judging->getJudgingid(),
1211+
'priority' => $priority,
1212+
'teamid' => $team->getTeamid(),
1213+
'teampriority' => $teamPriority,
1214+
]
1215+
);
12131216
}
12141217

12151218
public function getImmutableCompareExecutable(ContestProblem $problem): ImmutableExecutable

webapp/src/Service/RejudgingService.php

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Doctrine\ORM\EntityManagerInterface;
1717
use Doctrine\ORM\NonUniqueResultException;
1818
use Doctrine\ORM\NoResultException;
19+
use Ramsey\Uuid\Uuid;
1920

2021
class RejudgingService
2122
{
@@ -99,43 +100,62 @@ public function createRejudging(
99100
}
100101

101102

102-
$this->em->wrapInTransaction(function () use (
103-
$priority,
104-
$singleJudging,
105-
$judging,
106-
$rejudging
107-
) {
108-
$this->em->getConnection()->executeStatement(
109-
'UPDATE submission SET rejudgingid = :rejudgingid WHERE submitid = :submitid AND rejudgingid IS NULL',
110-
[
111-
'rejudgingid' => $rejudging->getRejudgingid(),
112-
'submitid' => $judging->getSubmissionId(),
113-
]
114-
);
115-
116-
if ($singleJudging) {
117-
$teamid = $judging->getSubmission()->getTeamId();
118-
if ($teamid) {
119-
$this->em->getConnection()->executeStatement(
120-
'UPDATE team SET judging_last_started = null WHERE teamid = :teamid',
121-
[ 'teamid' => $teamid ]
122-
);
123-
}
103+
// $this->>em->wrapInTransaction flushes the entity manager, which is pretty slow.
104+
// So use the direct connection transaction API here.
105+
$this->em->getConnection()->beginTransaction();
106+
107+
$this->em->getConnection()->executeStatement(
108+
'UPDATE submission SET rejudgingid = :rejudgingid WHERE submitid = :submitid AND rejudgingid IS NULL',
109+
[
110+
'rejudgingid' => $rejudging->getRejudgingid(),
111+
'submitid' => $judging->getSubmissionId(),
112+
]
113+
);
114+
115+
if ($singleJudging) {
116+
$teamid = $judging->getSubmission()->getTeamId();
117+
if ($teamid) {
118+
$this->em->getConnection()->executeStatement(
119+
'UPDATE team SET judging_last_started = null WHERE teamid = :teamid',
120+
[ 'teamid' => $teamid ]
121+
);
124122
}
123+
}
125124

126-
// Give back judging, create a new one.
127-
$newJudging = new Judging();
128-
$newJudging
129-
->setContest($judging->getContest())
130-
->setValid(false)
131-
->setSubmission($judging->getSubmission())
132-
->setOriginalJudging($judging)
133-
->setRejudging($rejudging);
134-
$this->em->persist($newJudging);
135-
$this->em->flush();
136-
137-
$this->dj->maybeCreateJudgeTasks($newJudging, $priority);
138-
});
125+
// Give back judging, create a new one.
126+
// Use a direct query to speed things up.
127+
$this->em->getConnection()->executeStatement(
128+
'INSERT INTO judging (cid, valid, submitid, prevjudgingid, rejudgingid, uuid)
129+
VALUES (:cid, 0, :submitid, :prevjudgingid, :rejudgingid, :uuid)',
130+
[
131+
'cid' => $judging->getContest()->getCid(),
132+
'submitid' => $judging->getSubmissionId(),
133+
'prevjudgingid' => $judging->getJudgingId(),
134+
'rejudgingid' => $rejudging->getRejudgingid(),
135+
'uuid' => Uuid::uuid4()->toString(),
136+
]
137+
);
138+
$newJudgingId = $this->em->getConnection()->lastInsertId();
139+
$newJudging = $this->em->getRepository(Judging::class)
140+
->createQueryBuilder('j')
141+
->join('j.submission', 's')
142+
->join('s.contest_problem', 'cp')
143+
->join('s.language', 'l')
144+
->join('l.compile_executable', 'e')
145+
->join('cp.problem', 'p')
146+
->leftJoin('p.compare_executable', 'ce')
147+
->leftJoin('ce.immutableExecutable', 'ice')
148+
->leftJoin('p.run_executable', 're')
149+
->leftJoin('re.immutableExecutable', 'ire')
150+
->select('j', 's', 'cp', 'l', 'e', 'p', 'ce', 'ice', 're', 'ire')
151+
->andWhere('j.judgingid = :judgingid')
152+
->setParameter('judgingid', $newJudgingId)
153+
->getQuery()
154+
->getSingleResult();
155+
156+
$this->dj->maybeCreateJudgeTasks($newJudging, $priority);
157+
158+
$this->em->getConnection()->commit();
139159

140160
if (!$first) {
141161
$log .= ', ';

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy