Rust translations of C code often run slower but can be optimized

Where Does the Performance Go? Understanding and Recovering Performance Regressions in C-to-Rust Translation

Artificial IntelligenceProgramming Languages

Summary

When converting C programs to Rust to improve memory safety, the translated Rust code sometimes runs slower than the original C. The authors studied why this slowdown happens and found nine common reasons related to extra work done at runtime, missed compiler optimizations, and old C-style programming patterns. They created an AI-based tool that spots these issues in translated Rust code and applies safe fixes that speed it up. This tool can make translated Rust code match or even beat the original C programs in speed while keeping their behavior the same.

What this means in practice

  • For software migration teams: Improve performance of C projects migrated to Rust by automatically detecting and fixing common slowdown causes in translated code.
  • For compiler engineers: Use insights about missed optimizations and runtime overheads to enhance compiler passes for translated Rust code from C.

Authors

Zhiqiang Yuan, Chong Wang, Zhenhao Zhou, Junwei Liu, Xin Peng

Abstract

Rust is increasingly adopted as a memory-safe successor to C, and transpilers such as \crust{} can migrate entire C projects while preserving their behavior. Preserving behavior, however, does not guarantee preserving performance. We study this gap on 20 real-world C projects and their \crust{} translations. On the eight projects used for analysis, the translated Rust is more than 3\% slower than the original C on 12 of 19 operations, by up to 62.2\%. By comparing execution-cost profiles, optimized LLVM IR, and compiler optimization remarks across each C--Rust pair, we trace these slowdowns to nine recurring performance issues, spanning residual runtime work, missed compiler optimizations, and C-style source patterns, and derive an optimization direction for each. We then present \ourtool{}, an LLM-based approach that encodes these issues as reusable optimization rules to recover the performance of translated Rust. \ourtool{} profiles each project to locate hot functions and matches them against rule-specific patterns. The LLM then checks each rule's rewrite preconditions against the project context before rewriting, and a rewrite is kept only if it passes both functional and performance validation. On 41 operations from twelve held-out projects, \ourtool{} preserves C outputs on all tested workloads and speeds up 40 operations over the \crust{} translations, 18 of which end up faster than the original C. It outperforms the general-purpose coding agent \codex{} on 31 of the 37 operations where both preserve C outputs, and outperforms its own variant without rule guidance on 34 of the 41 operations.