perf(提交): 交 C / C++ 不用再干等:编得过的代码不再先送判题机编一遍,全班一起交时不会卡上好几秒
Deploy / deploy (push) Canceled after 0s

提交前的自动格式化原来每次都先在判题机上编一次(防止 clang-format 把编不过的几行并成
一行)。服务器只有两核、还要和判题抢 CPU,按两核实测:40 人同时交 C,这一步中位 1.8 秒、
最慢 2.7 秒;40 人同时交 C++(iostream),全部撞上 8 秒超时。而且等完之后判题还要再编一遍。

现在先跑 clang-format(十几毫秒),只有它真把学生原来分开的两行并成一行时才去判题机编。
大括号挪到上一行、} else 接上不算并行。拿本机库里的真实提交核过:编得过的 C 只有 1.2%、
C++ 2.1% 还会去编;编不过又被并了行的照样拦住、原样返回。

顺带:格式化不再给 #include 排序、不再把超长的 printf 字符串拆成两截(学生看不懂
"……" "……" 这种写法,它们也是误判的主要来源)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-14 12:19:48 +08:00
1 parent 7881431fa9
commit 797b41751e
2 files changed
+60 -21

No files matched your search

+22 -20
View File
@@ -28,7 +28,7 @@ import {
requireContestAccess,
type ContestEnv,
} from "../services/contest"
import { CodeFormatError, formatCode } from "../services/format-code"
import { CodeFormatError, formatCode, mergesLines } from "../services/format-code"
import { getBooleanOption } from "../services/options"
import { problemSetLockCutoffs } from "../services/problemset"
import { consumeToken } from "../services/throttling"
@@ -246,28 +246,30 @@ submissionRoutes.post("/submissions/:id/rejudge", requireTeacher, async (c) => {
submissionRoutes.post("/code/format", requireAuth, async (c) => {
const parsed = await parseBody(c, formatCodeRequestSchema, "Invalid format payload")
if (!parsed.success) return parsed.response
// C / C++ 编不过就原样返回,不格式化(理由见 judge/run.ts 的 compileFails)。
// 代码照常提交、照常判成编译错误,只是不改动学生的代码
const { code: source, language, problemId } = parsed.data
if (language === "c" || language === "cpp") {
const judgeLanguage = language === "c" ? "C" : "C++"
const [problem] =
problemId === undefined
? []
: await db
.select({ template: schema.problem.template })
.from(schema.problem)
.where(eq(schema.problem.id, problemId))
.limit(1)
const rawTemplate = problem ? templateForLanguage(problem.template, judgeLanguage) : null
const template = rawTemplate ? parseProblemTemplate(rawTemplate) : null
const full = template ? `${template.prepend}\n${source}\n${template.append}` : source
if (await compileFails(judgeLanguage, full)) {
return success(c, { code: source } satisfies FormatCodeResponse)
}
}
try {
const code = await formatCode(source, language)
// C / C++ 编不过就原样返回,不格式化(理由见 judge/run.ts 的 compileFails)。
// 代码照常提交、照常判成编译错误,只是不改动学生的代码。
// 只有 clang-format 真把两行并成一行时才去判题机编:判题机和判题抢同一台机器的 CPU,
// 全班一起交 C++ 时每人都要排满 8 秒超时;而编得过的代码九成以上根本不并行
if ((language === "c" || language === "cpp") && mergesLines(source, code)) {
const judgeLanguage = language === "c" ? "C" : "C++"
const [problem] =
problemId === undefined
? []
: await db
.select({ template: schema.problem.template })
.from(schema.problem)
.where(eq(schema.problem.id, problemId))
.limit(1)
const rawTemplate = problem ? templateForLanguage(problem.template, judgeLanguage) : null
const template = rawTemplate ? parseProblemTemplate(rawTemplate) : null
const full = template ? `${template.prepend}\n${source}\n${template.append}` : source
if (await compileFails(judgeLanguage, full)) {
return success(c, { code: source } satisfies FormatCodeResponse)
}
}
return success(c, { code } satisfies FormatCodeResponse)
} catch (error) {
if (error instanceof CodeFormatError) {