Overhead (speed and junk) of calls to functions that do nothing

I am trying to reduce the cost of garbage collection / assembly for logging. I want to have a lot of logging operators that I could enable for debugging, but also be able to disable them for fast production.

I conducted a test when calling the following methods:

public static final isLogging = false; public static logObjs(Object[] params) { if(isLogging) System.out.println(params[0]); } public static log3Obj(Object a, Object b, Object c) { if(isLogging) System.out.println(a); } public static logInts(int a, int b, int c) { if(isLogging) System.out.println(a); } 

I compared functions using the driver method

 long sum = 0; for(int i = 0; i < 100000000; ++i) { int a = i; int b = i+1; int c = i+2; logFoo(a,b,c); sum += a; } 

logObjs (i, i + 1, i + 2) takes about 2 seconds for 1e8 iterations and produces a lot of garbage. The sources are, I suppose, autoboxing integers and creating Object [] for the # parameter variable.

log3Obj produces a lot (albeit less) of garbage and takes about 1.2 seconds; again, I guess autoboxing does happen.

logInts is very fast (0.2 sec), as fast as a loop without calling a function.

So, the problem is that although the function deterministically does nothing, autoboxing does occur. In my code, I would prefer isLogging not to be final, but rather it was a runtime parameter, but for this it is a simpler case (when the compiler can prove that the function does nothing) should work. Of course, I can replace all my logging statements.

 if(isLogging) logObjs(a, b, c); 

but it is very inelegant. I thought this is what JIT should take care of. I tried a bunch of compiler settings, but maybe something is missing there? How to make code not generate so much garbage without doing anything?

+4
source share
3 answers

This is very similar to this question: Will the Java optimizer remove the parameter construct for empty method calls?

As I wrote there: JIT understands very well that it does not need to do anything (a little less in your case, since it is more involved). But he does not seem to be doing this.

What I would like to suggest is to make several log methods, common with some vararg parameters and some overloaded ones that take integers and prevent autoboxing in the first place:

 Log(Object... arguments) { /* do logging */ } Log(Object a, Object b, Object c} { /* special case for 3 objects */ } Log(int a, int b, int c} { /* special case for 3 ints */ } 

UPDATE: even better, see Péter Török ', do not return the wheel password ...

+1
source

You really should prefer an existing logging framework such as Log4J, rather than reinventing the wheel. These guys have put more effort into optimizing their logging system than you have ever realistic. See the Performance section at the end of this short introduction to log4j .

Also, do not try to optimize prematurely. Most likely, making serious efforts to optimize logging reports (or, for that matter, no matter what part of your application) without real measurements and evidence that this actually improves the situation will not pay off.

+4
source

I think you should register what you need for writing, not for converting integers to objects.

Calling logObjs () or log3Obj () for log integers is just a waste of time - you are going to create temporary objects for boxing / unpacking and you will need to dispose of them. There is nothing you can do about it.

I suspect that most of the time when you are going to call logObjs (), you have to pass real objects to the function, in which case the cost of the GC is almost zero, since you will just pass references to these objects to logObjs (), and create or object deletion is not required.

Write a few logging functions that use different argument lists suitable for what you are going to write at that time. This is what I do. If I need to write a string and a 32-bit value, I have a logging API with these parameters, etc. No (or few) unnecessary / temporary object creation.

If you need to write 3 integers, write an API that accepts 3 integers. If you need to register a weeble object and a wobble object and a dont-fall-down object, then write an API for this. Minimize the effects of box / unobx / GC using the appropriate APIs for your logging functions.

+1
source

Source: https://habr.com/ru/post/1313541/


All Articles