-1

I have many of these types of logs generated throughout the application.

_logger.Debug(string.Format(
   "Object value is - {0}", 
    JsonConvert.SerializeObject(someDynamicObject)));

Now when in production, most of the time loglevel would be Error, hence above line would not log anything. The question is whether string.format is called and string operations are being done, or the JIT compiler is smart enough to remove away the whole call depending on log level? If not, then a lot of string operations are happening for no reason, and probably we should optimize these in a better way.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Harsh Kumar
  • 108
  • 1
  • 10
  • 1
    How is logging disabled, exactly? If it's by setting some state which *could* change at runtime, the JIT can't optimize away code which checks that state.... – canton7 Jun 11 '21 at 08:16
  • 2
    It will be evaluated (unless `Debug` is declared with `[Conditional(DEBUG)]`) or some such). If you are worried about performance, you could pass a `Func` to `Debug()` rather than an actual string, and only call the delegate if actually outputting a message. This assumes you can change the implementation of `Debug()`. – Matthew Watson Jun 11 '21 at 08:17
  • @canton7 Logger configuration is not changing at runtime as that is initialized by static config files. So theoretically, JIT compiler could be smart to decide that this line is not going to actually log anything, hence optimize away the code. – Harsh Kumar Jun 25 '21 at 08:38
  • @HarshKumar If it's configured by state which *could* change (e.g. by the application performing reflection), the JIT can't assume it will never change -- it doesn't have enough knowledge of the system to know that it's never going to perform reflection to change that config, for instance – canton7 Jun 25 '21 at 08:43

1 Answers1

1

The question is whether string.format is called and string operations are being done

The compiler will most likely not optimize this. Optimizing this would require the function to be inlined. This could allow the jitter to re-arrange the calls to only format the string after the log-level check. But I would not expect this to be done:

  • There are various requirements for a method to be inlined. Chances are one of these would prevent inlining.
  • The jitter would have to know that string.Format is pure, and does not have any side-effects. i.e. if omitting the call could possibly have any effect on the program.
  • It would have to be implemented, and have sufficient low performance impact for the jitter to be worth it.

Some logging frameworks have methods with a signature like one of the following to avoid this issue.

  • Log<T>(string str, T param1)
  • Log(string str, params object[] parameters)
  • Log(Action<string> messageGenerator)

Here is a list of overloads for nLog for a more complete example.

It might also be advisable to not log in tight loops and other performance sensitive parts of the application, and if you have to do that, pay special attention to performance.

JonasH
  • 28,608
  • 2
  • 10
  • 23