How much Java source code does it take to need 256MB of codecache? The author says they're using a service architecture where each transaction uses about 20 services. There's no indication of why their program is so huge.
Author here. We know 128MB codecache was not enough and 256MB was sufficient. I think we could have gotten by with less, e.g. 200MB, but we stopped experimenting once we found a value that worked. We don't have a complete understanding of why this app uses so much more codecache than other apps we've switched to Java 8. Now that we expose the codecache size in Datadog, I may try plotting code size vs codecache size f…
JRE 8 needs more codecache than before
21–30 of 38 posts
Re: JRE 8 needs more codecache than before
#22Typical problem of over tuning. Not every tunable needs to be tweaked (or worse cut'n'pasted somewhere from the internet). Your street cred as a admin does not depend on how many settings you can change. If they had just kept using the defaults everything would have been fine. That said 250MB is really a lot of code. Their binaries must be gigantic. This by itself likely already causes performance problems because al…
Re: JRE 8 needs more codecache than before
#23How much Java source code does it take to need 256MB of codecache? The author says they're using a service architecture where each transaction uses about 20 services. There's no indication of why their program is so huge.
Codecache is for compiled code, so it doesn't necessarily correlate to the original program's source code size. You can have the same methods inlined in many places, load the same classes in multiple class loaders (which means they are separate classes to the JVM), generate code at runtime, etc. For example, Presto is a SQL query engine that generates code for each query (a SQL query is effectively a program), so it…
Isn't the JVM more conservative about inlining already inlined methods? I can't find a cite right now, but I swear I've seen this when inspecting the compiler output.
Re: JRE 8 needs more codecache than before
#24Earlier quoted context omitted.
Author here. We know 128MB codecache was not enough and 256MB was sufficient. I think we could have gotten by with less, e.g. 200MB, but we stopped experimenting once we found a value that worked. We don't have a complete understanding of why this app uses so much more codecache than other apps we've switched to Java 8. Now that we expose the codecache size in Datadog, I may try plotting code size vs codecache size f…
Datadog employee here, you don't need to run your own collector to collect codecache usage. As it's exposed through JMX, the JMX collector can collect it http://docs.datadoghq.com/integrations/java/ . It doesn't by default though, so you'll need to configure it to collect the metrics from the "java.lang:name=Code Cache,type=MemoryPool" bean. We should add that in our default configuration.
Re: JRE 8 needs more codecache than before
#25How much Java source code does it take to need 256MB of codecache? The author says they're using a service architecture where each transaction uses about 20 services. There's no indication of why their program is so huge.
Codecache is for compiled code, so it doesn't necessarily correlate to the original program's source code size. You can have the same methods inlined in many places, load the same classes in multiple class loaders (which means they are separate classes to the JVM), generate code at runtime, etc. For example, Presto is a SQL query engine that generates code for each query (a SQL query is effectively a program), so it…
Re: JRE 8 needs more codecache than before
#26If the JVM has one bytecode compiler that it uses only during startup and another that it used the rest of the time, shouldn't it dump the bytecode generated by the first compiler from the cache at the point when it switches to the second compiler?
Now, sometimes optimizations can be "wrong", in the sense that something new has happened that invalidates an assumption used during second-tier compilation. Here's a real-world example: I have an interface and only one loaded class that implements that interface. The second-tier compiler will use this information to basically do this:
function doStuff(MyInterface a) {
if (a.getClass() != MyClass.class)
deoptimize();
// Do everything from here on assuming
// that a is an instance of MyClass.
// This includes inlining simple getter
// methods to pure field accesses, etc.
}
Now, when a second class that implements `MyInterface` is loaded and makes it to that function, it will hit the `deoptimize` branch and go back to first-tier or even interpreted mode. Eventually the function will be recompiled by both tiers with the new assumption -- two implementing classes.So, in the case of deoptimization, it can be a win to keep the first-tier code to fall-back to.
Re: JRE 8 needs more codecache than before
#27Beginning with Java 8, instead of having the VM to magically choose between using the client JIT (c1: think V8) or the server JIT (c2: think gcc -O2), the default configuration is to run in so called "tiered mode", first starts with the interpreter (as usual) then c1 (here keep the profile info) then c2. Because the code is compiled twice, you need a twice bigger code cache.
From my own experience, tiered compilation is nice when you run something interactive like an IDE (IntelliJ IDEA) and useless when you run a server app. That's said i've never had to have a 250MB code cache.
Re: JRE 8 needs more codecache than before
#28If the JVM has one bytecode compiler that it uses only during startup and another that it used the rest of the time, shouldn't it dump the bytecode generated by the first compiler from the cache at the point when it switches to the second compiler?
I think you meant the machine code. The Java compiler produces bytecode from Java source. The C1 and C2 bytecode compilers in the JVM convert bytecode to machine code. Yes, I agree if C2 recompiles something C1 already compiled, the C1-compiled machine code should be freed from the codecache.
Re: JRE 8 needs more codecache than before
#29If the JVM has one bytecode compiler that it uses only during startup and another that it used the rest of the time, shouldn't it dump the bytecode generated by the first compiler from the cache at the point when it switches to the second compiler?
The article's wording is a bit misleading here. The first-tier and second-tier compilers are always available throughout the entire lifetime of the program. The first-tier compiler performs very few optimizations, but compiles very quickly. It is a simple and literal compiler -- most direct translation of byte code to machine code. It's meant to be a quick win to get out of interpreted mode, which is vastly slower. T…
Re: JRE 8 needs more codecache than before
#30Earlier quoted context omitted.
Codecache is for compiled code, so it doesn't necessarily correlate to the original program's source code size. You can have the same methods inlined in many places, load the same classes in multiple class loaders (which means they are separate classes to the JVM), generate code at runtime, etc. For example, Presto is a SQL query engine that generates code for each query (a SQL query is effectively a program), so it…
> You can have the same methods inlined in many places Isn't the JVM more conservative about inlining already inlined methods? I can't find a cite right now, but I swear I've seen this when inspecting the compiler output.