United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-8006952 : CodeCacheFlushing degenerates VM with excessive codecache freelist iteration

Details
Type:
Bug
Submit Date:
2013-01-25
Status:
Resolved
Updated Date:
2016-06-28
Project Name:
JDK
Resolved Date:
2013-04-17
Component:
hotspot
OS:
generic
Sub-Component:
compiler
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
8
Fixed Versions:
hs25 (b29)

Related Reports
Backport:
Backport:
Backport:
Backport:
Relates:
Relates:

Sub Tasks

Description
Code cache flushing causes stop in compilation, contention on codecache lock and lots of wasted CPU cycles when the code cache gets full.

When uncommited codecache memory is less than the the size of the total memory on the freelist, we iterate the entire freelist for the largest block. This is done from ~8 places in the compiler broker. As long as the largest block is less than CodeCacheMinimumFreeSpace (1,5M) all compilation is halted and flushing is invoked. Since gathering a 1,5M continous freelist block will take some time, compilations is delayed, and regular flushing makes the freelist longer and longer. After a while it is very long, but still far from being continous. More and more time is spent iterating the freelist. All profile counters that overflow will end up checking the freelist. All compiler threads will check the freelist a few times before delaying compilation. In addition the freelist is accessed holding the codecache lock making the excessive iterating fully serilized. After a day or so a CPU core may spend 100% of its cycles banging the codecache locka and iterating the freelist. Also the application slows down when more and more code is flushed from the cache. 

This problem is mostly mainfested with tiered compilation since we compile and reclaim a lot more code. A clear symptom is when the VM has stopped compiling even though it reports it has enough free code cache. The problem is worse with big codecaches since the freelist will be more fragmented and get much longer before finding a continous block.

Workaround: Turn of code cache flushing.

Solution is probably not to require continous free memory. The cause for the threshold is to gaurantee space for adapters, and they are usually small and will fit anyway. 

                                    

Comments
This was actually a regression going from JRockit to JDK 7, so not a regression in our usual sense
                                     
2016-06-14
CodeCacheMinimumFreeSpace is 500k, not 1500k, and I don't believe is the problem here. CodeCacheFlushingMinimumFreeSpace is 1500k and appears to be the problem. It is what is being compared against the largest free block:

  static bool    needs_flushing()                { return largest_free_block() < CodeCacheFlushingMinimumFreeSpace; } 

And as long as needs_flushing() returns true, we don't compile:

  // If the compiler is shut off due to code cache flushing or otherwise,
  // fail out now so blocking compiles dont hang the java thread
  if (!should_compile_new_jobs() || (UseCodeCacheFlushing && CodeCache::needs_flushing())) {
    CompilationPolicy::policy()->delay_compilation(method());
    return NULL;
  } 
                                     
2013-03-19



Hardware and Software, Engineered to Work Together