PERF.LOG001
Debug.Log calls still cost time in a release build
Debug.Log survives into release builds. Both halves cost you: the log call itself goes through Unity’s logging pipeline (and writes to the player log), and — more often the real cost — the arguments are evaluated and the string is built before the call, every time, whether or not anything consumes the output.
// This allocates and formats on every frame, in your shipped build:
Debug.Log("Player at " + transform.position + " health " + health);
What the scan looks at
Runtime .cs files under Assets/ (anything inside an Editor/ folder is excluded — it isn’t in the build) and counts Debug.Log/Debug.LogFormat calls per file. Ten or more in one file is reported as a Warning; fewer is Info. Comments and string literals are excluded, but this is a text heuristic, not a compile-level analysis, so treat the count as close rather than exact.
Why it costs you
- String construction and boxing happen at the call site, before any log filtering.
Debug.unityLogger.logEnabled = falsestops the write, not the concatenation. - The write itself hits the player log file. On mobile that’s slower than people expect, and inside a per-frame loop it shows up in a profile.
- The allocations feed the GC, which is how “harmless logging” turns into a periodic frame spike.
How to fix it by hand
Wrap logging in your own class and mark it [Conditional], so the compiler removes the call and its arguments in builds where the symbol isn’t defined:
public static class Log
{
[System.Diagnostics.Conditional("ENABLE_LOGS")]
public static void Info(string message) => Debug.Log(message);
}
// Call sites stay readable, and compile to nothing without ENABLE_LOGS:
Log.Info($"Player at {transform.position}");
[Conditional] is the important detail — an if (enableLogs) guard still evaluates the string. Define ENABLE_LOGS in your development player settings and leave it out of release.
Alternatives: #if UNITY_EDITOR around editor-only diagnostics, and Player Settings ▸ Stack Trace set to None for Log, which cuts the per-call stack capture if you keep logging on in a shipping build deliberately.
What PerfLint does about it
Report-only, and deliberately not AI-fixable. Replacing log calls project-wide is a refactor with a design decision in it — which wrapper, which symbol, which calls are actually diagnostics you want in a release build. The finding gives you the file, the count, and a jump to the first occurrence, so you can decide where a wrapper is worth introducing.
The related build-size lever is IL2CPP managed stripping: see PROJ002.
Check your own project. The scan is free, runs entirely on your machine, and reports this rule with the exact assets that trip it — nothing is uploaded.
Last reviewed · All rules