5 ms·
Logger levels are mutable to allow switching them at runtime, JIT can not make an assumption that the log level will stay the same.
by isbvhodnvemrwvn 5y ago
Logger levels are mutable to allow switching them at runtime, JIT can not make an assumption that the log level will stay the same.
- akvadrako 5y agoSure it can, since the JIT has access to runtime information and all the code. It could reorder the steps so first the log level is checked, then that block is run.
- hamburglar 5y agolog.debug(“foo count: “ + fooHandler.incrementAndReturnFooCount()); Should the JIT call incrementAndReturnFooCount if debug logs are disabled? This is a long-recognized pitfall of C preprocessor macros that look like function calls but may simply be defined away, causing unexpected behavior.
- akvadrako 5y agoIt should call it if it has side effects, otherwise not. Java isn't C; the runtime can be a lot smarter.
- hamburglar 5y agoI guess I’m not up on the state of the art with respect to the JRE’s ability to determine whether arbitrary code has side effects. That’s quite a broad problem. If I write fizzbuzz but use log.debug for output, does it optimize my main() to be empty unless I run it with debug enabled?
- alserio 5y agoI believe the problem is just that the toString methods implicitly called when concatenating strings and objects, can execute side effects. And the JIT has to keep those effects if it cannot prove they are just heating up your CPU
- mannykannot 5y agoThat struck me at first as bizarre - but is it because one can override a toString method with something that has side-effects? (Or give a user-defined class a tosSring() with side-effects, I suppose.)
- alserio 5y agoWell, yes, you could simply put a System.out.println in there and it would be valid java
- salawat 5y agoI'm confused. Do people not overload toString() on a regular basis along with .equals() and .hashCode() anymore? Common case was prettyprinting of deep object structures, and yes, technically, you could update state while doing it, but dear God, why? Hell, API method names don't actually mean squat as far as the JVM is concerned. It's just the consensus of the community to go with convention over config. If everyone does the same thing with methods of the same name, it decreases cognitive overhead. Did I fall into an alternate dimension where 90% of Java seems to only use preexisting objects now, and people hardly ever write their own code? (No disrespect to the asker; it's just such a surprising question to stumble across, that mentally speaking, I had to deoptomize my mental model of the world to accommodate for people who may not have worked much with Java). I get functional is all the rage, but wow. Default toString() impl is inherited from Object, and basically gives you class and instance number.
- chrisseaton 5y ago> JIT can not make an assumption The whole point of a JIT is that it can make assumptions. 'Assumption' is literally the term used in the JIT to track things like this.
- mannykannot 5y agoJust because a JIT is "making assumptions", it does not mean it could or should make the assumptions needed for what you are calling for here. Generally speaking, optimizers should only be making semantically-neutral assumptions (optionally under the further assumption that the code fully conforms with any constraints the language spec. puts on program behavior, which is somewhat controversial in C.) Furthermore, a JIT can only spend a limited amount of resources in determining whether skipping the evaluation of an argument expression would be semantically neutral. (At this point, functional-programming enthusiasts are rolling their eyes...) If logging was part of the language, one could simply rule by fiat that arguments shall not be evaluated unless logging is enabled, but log4j is just another collection of user-defined classes, and gets no special treatment.
- eropple 5y agoYou might want to refresh yourself on who you're talking to here on this one. I'm sure that there are certainly people more familiar with the JIT behavior of HotSpot and Graal out there, but I don't know that any of them post here on the topic. I'm not saying that when it comes to the JVM's optimization behaviors that I'd jump without checking that there's water on Chris's assurance, but I'm not saying I wouldn't either.
- mannykannot 5y agoI am duly chastened, and ready to learn what boneheaded mistakes I am making. For one thing, I take it that that the analysis is tractable for most practical cases.
- mannykannot 5y agoIt occurred to me today that, somewhat ironically, JNDI+LDAP calls appear (at least to me on first sight) to be prime examples of expressions that would be difficult for a JIT optimizer to analyze for side-effects, given that this is a mechanism for making remote calls. If I am mistaken in so thinking, I would be genuinely interested in learning about how it is done. To be clear, I am not suggesting that these sort of expressions are inherently insecure - that would depend, I think, on whether they involve user input in a way that allows an attacker to take control of the call. A hard-coded JNDI lookup from the arguments list of a log4j call might be inefficient, but no less secure than if made anywhere else.
- callmeal 5y ago>Logger levels are mutable to allow switching them at runtime, JIT can not make an assumption that the log level will stay the same. Java HotSpot can make and verify that assumption. And switch code when the level changes.
- nbevans 5y agoSo you've moved the IF statement that was checking the logging level from the program code into the JIT. Great. No saving. (And I doubt it actually does this - as it's not gaining anything)
- molyss 5y agoYou didn’t move the IF. you literally removed it. If (a) DoExpensiveStuff()); Becomes When modifyA() RecompileIfWithNewAValue(); As long as you call the initial if more often than you modify (a), you’re fine (and the JVM was able to see that you called your if 10k times without modifying the value of (a) even once)
- ludamad 5y agoRespectfully, your post is very wrong :) JIT compilers are very fast and run once to prep the code that will run many times. If you had flat code that was always run exactly once the games would be lesser, yes