Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
14
Question by Steven-1 · Jun 05, 2011 at 12:46 PM · buildperformancedebuglog

Debug.Log() in build

I was assuming writing debug.log() would have no effect on the performance in the build.

I noticed that my menu runned at about 4 fps in the editor, which turned to 500 fps after removing all the debug.log there. However, it seems that my menu also runs very slowly (presumably also around 4 fps) in the build when I still have these debug.log there.

This leads me to believe that debug.log is still executed (but fails), rather than removed altogether.

Is this the case ? because that would be quite annoying, as I'd have to remove all the debug stuff if I want to make a smooth build.

EDIT:

Apparently this is the case and intentional. Thanks for the answers guys.

I think I'm gonna write a wrapper that's something like:

 static function DebugLog(text:String)
 { 
     if (Debug.isDebugBuild) 
         Debug.Log(text);
 }
Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image The-IT664 · Apr 29, 2013 at 12:49 AM 1
Share

I just wanted to add a comment regarding making a static function to anyone considering it. By adding a static function, you are changing the call stack, specifically the top level of the call stack which is stored with the output message. As a result, you will no longer be able to double click on the editor output messages and be taken to the line of code from which the log originated, as you will ins$$anonymous$$d be taken to the new static function you created.

avatar image Eric5h5 · Apr 29, 2013 at 01:27 AM 0
Share

You can get around that by making the static function into a DLL, or you can not bother with that at all and just turn off "Use Player Log" in the player settings. (I don't think that option existed when this question was originally asked.)

avatar image semiessessi · Feb 20, 2014 at 02:18 PM 0
Share

its understandable to think this is a bug. stripping debug logging functionality from release builds is not uncommon and has certainly been a part of various certification requirements over the years... unity is the first engine i've worked with properly (including scratch built own engines) that doesn't include this functionality out of the box along with useful code-triggered breakpoint and assert functionality... however, given the enormous stack of technology involved i'm inclined to be a little forgiving. Unity is a strange environment compared to 'old school' native game development - performance considerations are very different - usual advice like not using RTTI and forbidding exceptions can not apply because these features are baked into the platform already... what was once an unacceptable performance cost is now acceptable as a trade off for ease of use by virtue of modern horsepower.

avatar image Eric5h5 · Feb 21, 2014 at 11:24 AM 0
Share

@semiessessi: it does have the option to remove debug log output out of the box; see my previous comment. Also it does breakpoints in code; see the section in the docs about the debugger.

avatar image Gerold_Meisinger · Sep 08, 2015 at 09:59 AM 0
Share

Another reason why this may be useful is because you want to disable logging for plugins too.

9 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by zwacky · Jun 05, 2011 at 01:04 PM

can't think of debug.log to cause such performance loss other than due to exceptions, but you may want to add a static variable that defines whether you wan't to log or not. this way you don't have to delete every debug.log within the code.

 static var DEBUG : boolean = true;
 ...
 if (DEBUG) Debug.Log("logging");
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Steven-1 · Jun 05, 2011 at 01:43 PM 0
Share

Thanks. It caused such performance loss because I call it about 50 times per frame in the menu. And yeah, a way so I don't have to this manually would be better than just deleting or commenting it out each time. I think I'm gonna write a wrapper that's something like: static function DebugLog(text:String) { if (Debug.isDebugBuild) Debug.Log(String); }

avatar image yoyo · Aug 15, 2013 at 06:55 PM 1
Share

In a build, Unity's Debug.Log statement will do a bunch of stack trace parsing and then write to a file, so yes, it is that slow.

avatar image semiessessi · Feb 20, 2014 at 02:11 PM 2
Share

I'd recommend using preprocessor to do this if possible - it will save the compile time and potentially run-time checks (i have no idea how sufficiently smart the compiler is... they may or may not be removed - easier to not know imo). using custom preprocessor directives on a build is documented here: https://docs.unity3d.com/Documentation/$$anonymous$$anual/PlatformDependentCompilation.html

avatar image
19

Answer by tteneder · Jul 16, 2015 at 12:36 PM

I have another alternative:

Create a custom "Debug" class in global space, that get's used in release builds only and make its Log methods conditional:

 #if DEBUG
 #define VERBOSE
 #endif
 
 #if !UNITY_EDITOR && !VERBOSE
 using UnityEngine;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
 
 public static class Debug {
 
     [Conditional("VERBOSE_EXTRA")]
     public static void LogInfo(string message, UnityEngine.Object obj = null) {
         UnityEngine.Debug.Log(message, obj);
     }
 
     [Conditional("VERBOSE")]
     public static void Log(string message, UnityEngine.Object obj = null) {
         UnityEngine.Debug.Log(message, obj);
     }
 
     public static void LogWarning(string message, UnityEngine.Object obj = null) {
         UnityEngine.Debug.LogWarning(message, obj);
     }
 
     public static void LogError(string message, UnityEngine.Object obj = null) {
         UnityEngine.Debug.LogError(message, obj);
     }
 
     public static void LogException(System.Exception e) {
         UnityEngine.Debug.LogError(e.Message);
     }
 }
 #endif

The main advantage is, that the log usage doesn't differ at all, so it's easy to introduce it anytime:

 Debug.Log("Somethings going on here");

Note: I still want Warnings and Errors to be logged, so I didn't make them conditional. Starting with Unity 5.1, DEBUG gets defined automatically as soon as you create a development build.

Downside: UnityEngine.Debug methods other then Log, LogInfo, LogWarning and LogError have to be issued with the complete namespace. For example:

 UnityEngine.Debug.DrawLine(...);

This can easily be resolved by wrapping them all in our own Debug class. Feel free to do that, I simply was too lazy :)


My thoughts on how I got to this solution:

The solutions presented so far have one thing in common, they utilize an if statement. Downsides:

  • you actually have to write it out on every log occasion.

  • It generates an unnecessary evaluation at runtime.

You could argue that the impact of the if statement is minimal, but that didn't keep me from optimizing.

One way would be to use preprocessor directives, which totally work, but you'd still have to wrap every log statement with ugly code:

 #if DEBUG
     Debug.Log("Somethings going on here");
 #endif

To get rid of this I wrote my own class, which wrapped the Log calls with conditional methods. I assume the calls don't even exist in runtime assemblies. Something like that:

 public class Logging {
     [Conditional("DEBUG")]
     public static void Log(string message) {
         Debug.Log(message);
     }
 }

This works, but has these flaws:

  • You have to change every "Debug.Log" call to "Logging.Log"

  • In the Editor, you lose the feature of double clicking logs and jumping directly to the original place where the Log was issued, since you'll now end up in our new Logging class all the time. This is a major time waste.

Next step: rename the Logging class to "Debug". Since this new Debug class is in global namespace it automatically gets used instead of Unity's UnityEngine.Debug if you use it without the complete namespace when calling it. You now don't need to change Debug.Log calls at all, though the Editor click redirection still won't work.

Our Debug class now prevents Logs in non DEBUG environments. As the last step I put the whole class into preprocessor statements that enable it only outside the Editor in non development builds or if you add the scripting define symbol "VERBOSE".

Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Gerold_Meisinger · Sep 08, 2015 at 10:22 AM 0
Share

A downside with occupying the global Debug namespace however is that scripts using other Debug classes (like System.Diagnostics.Debug) start to complain about missing methods (like Assert).

avatar image tteneder Gerold_Meisinger · Sep 25, 2015 at 08:20 PM 0
Share

hi meisi :) Your right, but since I didn't use Assert so far, I'm fine with it. There probably is no ideal solution atm.

avatar image Paulius-Liekis · Dec 07, 2015 at 10:51 AM 0
Share

$$anonymous$$aybe you've managed to find a solution for double click issue?

avatar image tteneder Paulius-Liekis · Dec 07, 2015 at 12:17 PM 0
Share

what issue do you mean? Double clicking log messages in Editor should work, since my custom Debug class is only compiled/used in non-editor and non-debug builds.

avatar image pwnd · Feb 20, 2018 at 01:14 PM 1
Share

This does not work in current Unity versions anymore. You have to either add the define symbol in the unity player settings or add the define in all scripts that use our updated Debug class.

Just spend 2 hours trying to figure out why this was not working.

See: https://forum.unity.com/threads/conditionalattribute-not-working.469720/#post-3157609

avatar image eco_bach · May 30, 2018 at 02:12 PM 0
Share

This is brilliant! Similar to a global debug Trace class I created from Flash days:) So with this method you can leave ALL your Debug statements in your code and be assured they will NOT be called and impact performance in your release build, correct?

avatar image tteneder eco_bach · May 30, 2018 at 02:28 PM 0
Share

Correct! Been using it in production for years now. I just reassured by looking at the C++ code generated by IL2CPP. The log commands get stripped away completely!

avatar image LandonC · Oct 13, 2019 at 09:27 AM 0
Share

It looks very useful but what should I do If I would like to see the debug messages on debug mode only? Something like this?

       #if VERBOSE
       #define DEBUG
       #endif

 

avatar image tteneder LandonC · Oct 13, 2019 at 08:55 PM 0
Share

Yes, I think that should work

avatar image
15

Answer by xzodia · Sep 25, 2015 at 02:56 PM

I liked @atti 's solution, and decided to finish it off. Also added a few extra methods that auto concat args.

 #if DEBUG || UNITY_EDITOR
 #define VERBOSE
 #endif
 
 #if UNITY_EDITOR
 #define VERBOSE_EXTRA
 #endif
 
 using UnityEngine;
 using System.Diagnostics;
 using UnityEngine.Internal;
 using System;
 
 public static class Debug
 {
     //
     // Summary:
     //     Opens or closes developer console.
     public static bool developerConsoleVisible { get { return UnityEngine.Debug.developerConsoleVisible; } set { UnityEngine.Debug.developerConsoleVisible = value; } }
     //
     // Summary:
     //     In the Build Settings dialog there is a check box called "Development Build".
     public static bool isDebugBuild { get { return UnityEngine.Debug.isDebugBuild; } }
 
     //
     // Summary:
     //     Assert the condition.
     [Conditional("UNITY_ASSERTIONS")]
     public static void Assert(bool condition)
     {
         UnityEngine.Debug.Assert(condition);
     }
     //
     // Summary:
     //     Assert the condition.
     [Conditional("UNITY_ASSERTIONS")]
     public static void Assert(bool condition, string message)
     {
         UnityEngine.Debug.Assert(condition, message);
     }
     //
     // Summary:
     //     Assert the condition.
     [Conditional("UNITY_ASSERTIONS")]
     public static void Assert(bool condition, string format, params object[] args)
     {
         UnityEngine.Debug.Assert(condition, format, args);
     }
     public static void Break()
     {
         UnityEngine.Debug.Break();
     }
     public static void ClearDeveloperConsole()
     {
         UnityEngine.Debug.ClearDeveloperConsole();
     }
     public static void DebugBreak()
     {
         UnityEngine.Debug.DebugBreak();
     }
     //
     // Summary:
     //     Draws a line between specified start and end points.
     public static void DrawLine(Vector3 start, Vector3 end)
     {
         UnityEngine.Debug.DrawLine(start, end);
     }
     //
     // Summary:
     //     Draws a line between specified start and end points.
     public static void DrawLine(Vector3 start, Vector3 end, Color color)
     {
         UnityEngine.Debug.DrawLine(start, end, color);
     }
     //
     // Summary:
     //     Draws a line between specified start and end points.
     public static void DrawLine(Vector3 start, Vector3 end, Color color, float duration)
     {
         UnityEngine.Debug.DrawLine(start, end, color, duration);
     }
     //
     // Summary:
     //     Draws a line between specified start and end points.
     public static void DrawLine(Vector3 start, Vector3 end, [DefaultValue("Color.white")] Color color, [DefaultValue("0.0f")] float duration, [DefaultValue("true")] bool depthTest)
     {
         UnityEngine.Debug.DrawLine(start, end, color, duration, depthTest);
     }
     //
     // Summary:
     //     Draws a line from start to start + dir in world coordinates.
     public static void DrawRay(Vector3 start, Vector3 dir)
     {
         UnityEngine.Debug.DrawRay(start, dir);
     }
     //
     // Summary:
     //     Draws a line from start to start + dir in world coordinates.
     public static void DrawRay(Vector3 start, Vector3 dir, Color color)
     {
         UnityEngine.Debug.DrawRay(start, dir, color);
     }
     //
     // Summary:
     //     Draws a line from start to start + dir in world coordinates.
     public static void DrawRay(Vector3 start, Vector3 dir, Color color, float duration)
     {
         UnityEngine.Debug.DrawRay(start, dir, color, duration);
     }
     //
     // Summary:
     //     Draws a line from start to start + dir in world coordinates.
     public static void DrawRay(Vector3 start, Vector3 dir, [DefaultValue("Color.white")] Color color, [DefaultValue("0.0f")] float duration, [DefaultValue("true")] bool depthTest)
     {
         UnityEngine.Debug.DrawRay(start, dir, color, duration, depthTest);
     }
 
     [Conditional("VERBOSE_EXTRA")]
     public static void LogInfo(object message, UnityEngine.Object context = null)
     {
         UnityEngine.Debug.Log(message, context);
     }
     [Conditional("VERBOSE_EXTRA")]
     public static void LogInfoCat(params object[] args)
     {
         UnityEngine.Debug.Log(string.Concat(args));
     }
     //
     // Summary:
     //     Logs message to the Unity Console.
     [Conditional("VERBOSE")]
     public static void Log(object message, UnityEngine.Object context = null)
     {
         UnityEngine.Debug.Log(message, context);
     }
     //
     // Summary:
     //     Logs message to the Unity Console.
     [Conditional("VERBOSE")]
     public static void LogCat(params object[] args)
     {
         UnityEngine.Debug.Log(string.Concat(args));
     }
     //
     // Summary:
     //     A variant of Debug.Log that logs an error message to the console.
     public static void LogError(object message, UnityEngine.Object context = null)
     {
         UnityEngine.Debug.LogError(message, context);
     }
     //
     // Summary:
     //     A variant of Debug.Log that logs an error message to the console.
     public static void LogErrorCat(params object[] args)
     {
         UnityEngine.Debug.LogError(string.Concat(args));
     }
     //
     // Summary:
     //     Logs a formatted error message to the Unity console.
     public static void LogErrorFormat(string format, params object[] args)
     {
         UnityEngine.Debug.LogErrorFormat(format, args);
     }
     //
     // Summary:
     //     Logs a formatted error message to the Unity console.
     public static void LogErrorFormat(UnityEngine.Object context, string format, params object[] args)
     {
         UnityEngine.Debug.LogErrorFormat(context, format, args);
     }
     //
     // Summary:
     //     A variant of Debug.Log that logs an error message to the console.
     public static void LogException(Exception exception)
     {
         UnityEngine.Debug.LogException(exception);
     }
     //
     // Summary:
     //     A variant of Debug.Log that logs an error message to the console.
     public static void LogException(Exception exception, UnityEngine.Object context)
     {
         UnityEngine.Debug.LogException(exception, context);
     }
     //
     // Summary:
     //     Logs a formatted message to the Unity Console.
     [Conditional("VERBOSE")]
     public static void LogFormat(string format, params object[] args)
     {
         UnityEngine.Debug.LogFormat(format, args);
     }
     //
     // Summary:
     //     Logs a formatted message to the Unity Console.
     [Conditional("VERBOSE")]
     public static void LogFormat(UnityEngine.Object context, string format, params object[] args)
     {
         UnityEngine.Debug.LogFormat(context, format, args);
     }
     //
     // Summary:
     //     A variant of Debug.Log that logs a warning message to the console.
     public static void LogWarning(object message, UnityEngine.Object context = null)
     {
         UnityEngine.Debug.LogWarning(message, context);
     }
     //
     // Summary:
     //     A variant of Debug.Log that logs a warning message to the console.
     public static void LogWarningCat(params object[] args)
     {
         UnityEngine.Debug.LogWarning(string.Concat(args));
     }
     //
     // Summary:
     //     Logs a formatted warning message to the Unity Console.
     public static void LogWarningFormat(string format, params object[] args)
     {
         UnityEngine.Debug.LogWarningFormat(format, args);
     }
     //
     // Summary:
     //     Logs a formatted warning message to the Unity Console.
     public static void LogWarningFormat(UnityEngine.Object context, string format, params object[] args)
     {
         UnityEngine.Debug.LogWarningFormat(context, format, args);
     }
 }

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image tteneder · Sep 25, 2015 at 08:21 PM 0
Share

Nice, thanks for sharing! I may adopt this.

avatar image SpAiK · Oct 27, 2015 at 09:04 AM 0
Share

So do I put this script anywhere in a project or does it have to be on a specific folder? And btw, how could I test this with an Android app?

avatar image tteneder SpAiK · Oct 27, 2015 at 10:23 AM 1
Share

The location of the script file is not important, as long as it is within the Assets folder.

To view logs on Android devices (I asume connection and deploying via USB is already working), you can use adb ( http://developer.android.com/tools/help/logcat.html ).

I personally use/prefer the "monitor" tool (Comes with the Android SD$$anonymous$$ within the "tools" folder). It's a GUI to logcat that lets you create filters.

avatar image
6

Answer by Peter G · Jun 05, 2011 at 01:12 PM

Debug.Log() is still called when you are in a build so it could have an effect on performance depending on how much you call it. On iOS, it will actually log your information into the internal profiler if you are connected to xCode.

Removing them all is one option. I would just comment them out, or you can do this like the scripting ref suggests:

 // Log some debug information only if this is a debug build
 if (Debug.isDebugBuild) {
     Debug.Log ("This is a debug build!");
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Jun 05, 2011 at 01:18 PM 0
Share

Right, see this page to see where the log output ends:
http://unity3d.com/support/documentation/$$anonymous$$anual/Log%20Files.html

avatar image Steven-1 · Jun 05, 2011 at 01:39 PM 0
Share

Thanks, so it is as I assumed. If it's intentional, I find it strange that unity calls it "Debug", as I would expect anything by that name to do nothing in the build. And yes, I meant "commenting them out" when I said "remove". I guess I best just make a wrapper for it, so I don't have to do this manually all the time.

avatar image Bunny83 · Jun 05, 2011 at 02:26 PM 2
Share

Debugging doesn't end with creating a build ;) If you have Debug.Logs that really should only work in the editor you can include it in a preprocesser if-statement #if UNITY_EDITOR #endif

avatar image
3

Answer by ZowPac · Jun 19, 2012 at 11:22 PM

I have definitely seen Debug.Log() be a performance problem. Even one can cause a little hiccup on a smallish platform if you have enough going on.

One thing I should mention that took me a little while to realize when I did a similar solution to your DebugLog() function is that often I would end up doing something like:

DebugLog("Here in Func() " + var1 + " / " + var2 + " / " + var3);

The string argument is evaluated whether or not you eventually log them, and they tend to be slow too - especially with concatenation. String.Format() is better, but still, I've come around to commenting these things out when not needed, and using #if UNITY_EDITOR for those I heavily rely on.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

27 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Why is Debug.Log so much slower on Windows than Mac? 3 Answers

Distribute terrain in zones 3 Answers

Massive performance drop Windows Store App 0 Answers

libil2cpp.sym, libil2cpp.so.debug, libunity.sym.so... What should i use for il2cpp debugging? 1 Answer

Performance hiccup in release build? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges