跳转至

Synthesizing Performance Constraints for Evaluating and Improving Code Efficiency

会议: NeurIPS 2025
arXiv: 2505.23471
代码: https://github.com/UChiSeclab/perfforge
领域: AIGC检测
关键词: 性能约束合成, 代码效率评估, Fuzzing, LLM代码优化, PerfForge

一句话总结

提出Wedge框架——通过LLM合成性能刻画约束(performance-characterizing constraints)指导约束感知模糊测试,生成能暴露代码性能瓶颈的压力测试输入,构建PerfForge基准,使LLM代码优化器(如Effi-Learner)多减24% CPU指令。

研究背景与动机

领域现状:LLM在代码优化上表现出色,但评估其效果缺乏能真正暴露性能瓶颈的测试输入。现有方法要么用随机输入,要么用简单的大规模输入,无法针对性地触发特定代码路径的性能问题。

现有痛点:LLM难以直接推理"什么输入触发什么性能瓶颈",因为这涉及从程序输入到局部执行路径的复杂映射。现有性能测试生成方法(EvalPerf、TG-prompt)效果有限。

核心矛盾:需要找到让"未优化代码极慢但优化后代码快"的输入,但这种输入的构造需要理解代码的内部性能特征。

切入角度:将问题分解——LLM擅长推理局部代码行为("这个循环什么条件下迭代最多次"),fuzzing擅长搜索满足约束的输入。

核心idea:LLM合成性能约束 → 约束插桩到程序 → 约束感知fuzzing自动搜索满足约束的压力输入。

方法详解

整体框架

三阶段pipeline:(1)对比执行profiling——比较快/慢输入的per-statement执行次数找瓶颈;(2)性能约束合成——LLM两阶段推理(NL描述→checker code)生成约束并插桩;(3)约束引导fuzzing——修改版AFL++使用LLM生成的约束感知mutator搜索压力输入。

关键设计

  1. 对比执行Profiling

    • 功能:从已有正确性测试中挖掘对比输入对(相似输入但执行成本差异大)
    • 核心思路:运行程序收集每个输入的 CPU 指令数,用匹配率+Jaccard相似度衡量输入相似度,用执行成本比衡量性能差异,选排名最高的 \((i_{slow}, i_{fast})\) 对。然后收集两次执行的 per-line hit count 差异
    • 设计动机:对比执行提供的诊断线索比单次执行更丰富,高相似度确保差异确实来自性能特征而非输入本身
  2. 性能约束合成(两阶段)

    • Phase 1(自然语言推理):LLM 比较快慢执行的 hit count,定位热点代码,推理"什么条件让这些行执行更多次",输出 NL 描述的约束集 \(\mathbb{C}\)
    • Phase 2(代码实现):LLM 将自然语言约束转化为可执行的 checker 代码(如 all(l[i] > l[i+1] for i in range(len(l)-1))),插桩到程序中作为新的分支
    • 设计动机:两阶段分解避免了直接要求 LLM 生成压力输入的困难——LLM 擅长局部行为推理,不擅长全程序输入→行为映射
  3. 约束感知Mutator

    • 功能:替换 AFL++ 的默认 bit-flip mutator,生成理解输入语法和性能约束的自定义 mutator
    • 核心思路:LLM 根据问题描述(输入语法)、性能约束 \(\mathbb{C}\)、对比输入对,生成 Python mutator 函数。迭代 generate-and-fix 保证鲁棒性
    • AFL++ 的 coverage-guided 机制天然将插桩的 checker 分支作为覆盖目标——覆盖新 checker 分支 = 找到满足性能约束的输入
    • 去掉约束感知 mutator 后指令数降 3.9×(消融最关键组件)

实验关键数据

主实验

方法 平均指令数(×10⁸) Win rate 平均Slowdown
Wedge 5.96 60% 363×
TG-prompt 3.87 (↓1.5×) 12% 275×
PerfFuzz 3.29 (↓1.8×) 11% 149×
EvalPerf_slow 3.23 (↓1.8×) 8% 146×

代码优化驱动效果(Effi-Learner + GPT-4o)

输入源 执行时间减少 CPU指令减少
15.66% 31.39%
CC_default 22.57% 39.89%
PerfForge 26.47% 49.31%

消融实验

配置 平均指令数(×10⁸) vs Full
Full Wedge 5.96 -
WedgeNoInstr(去掉checker插桩) 4.02 ↓1.5×
WedgeDefaultMut(用AFL++默认mutator) 1.54 ↓3.9×
AFL++(无约束无插桩) 1.49 ↓4.0×

Pie 代码优化公平评估

PerfForge 评测发现 Pie 优化的实际加速比比其声称的(基于正确性测试)更高:指令数加速 24%-149%,物理时间加速 5%-27%。7%-48% 更多的程序实际被有意义地优化。

关键发现

  • 约束满足输入比违反输入慢 38.6×,在 92.84% 的程序上显著更慢——验证了约束的性能刻画能力
  • 约束感知 mutator 贡献最大(去掉后指令数降 3.9×),checker 插桩次之(去掉降 1.5×)
  • 小输入 (<1KB) 优势更大 (3× slowdown over baselines),证明性能压力来自实现瓶颈而非纯粹输入长度
  • 评测数据集:CodeContests 154 个问题、33,020 个 C++ 程序,fuzzing 每个解 1 小时

亮点与洞察

  • LLM+Fuzzing的精妙分工:LLM做"理解"(约束推理),fuzzing做"搜索"(满足约束的输入生成),各自发挥优势。
  • PerfForge作为代码优化的加速器:不仅是评测工具,更能反馈驱动LLM优化器找到更好的优化——形成evaluation→improvement闭环。

局限与展望

  • 依赖 LLM 生成正确的约束 checker 代码,复杂程序可能失败
  • 仅在竞赛题上验证(CodeContests),工业代码和仓库级代码的适用性未测
  • fuzzing 每个解 1 小时的开销较大,实际部署需考虑效率
  • 约束质量完全依赖 LLM 的代码理解能力,对未见过的算法模式可能表现不佳

相关工作与启发

  • vs EvalPerf:EvalPerf 通过 scale 参数控制输入大小,本质是长度压力测试;Wedge 针对具体代码实现生成结构化约束,更精准
  • vs PerfFuzz:PerfFuzz 用 edge hit count 引导 fuzzing,但没有显式的性能约束,最终还是生成长度压力输入
  • vs TG-prompt:直接提示 LLM 生成压力输入,要求端到端推理全程序行为,对 LLM 来说太难
  • 对 LLM agent 的代码优化能力评测有重要参考价值——好的评测输入能驱动更好的优化

评分

  • 新颖性: ⭐⭐⭐⭐⭐ 性能约束合成+约束引导fuzzing的组合全新
  • 实验充分度: ⭐⭐⭐⭐ 多基准、多消融、闭环验证
  • 写作质量: ⭐⭐⭐⭐ 动机清晰,方法描述系统
  • 价值: ⭐⭐⭐⭐⭐ 对代码效率评测和LLM代码优化都有直接价值