JDK-8013169 : consolidate MethodData and MethodCounters pointers in Method struct
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2013-04-24
  • Updated: 2017-03-28
  • Resolved: 2017-03-28
Related Reports
Relates :  
Relates :  
Relates :  
Description
The work in JDK-8010862 consolidates counters into one optional structure.  Further optimization is desirable.

Since the lifetimes of MethodData and MethodCounters are similar, there should be a single pointer.
Whichever structure is less frequent could be linked from the more frequent one, or they could be concatenated (which seems the likely thing to do). 

Please update the comment in the header file that documents the structure; it is currently inaccurate.

Consider overloading a "warm-up counter" into the initially NULL _method_counters field.  A value of (say) up to 256 could be stored into the pointer field, and instead of a null check, do a range check.  That will make many cold yet active methods not create a counter.  (Yes, I like this kind of stuff, even if the debuggers hate it.  But a debugger will print a small integer pseudo-pointer easily enough.)


Comments
Not a priority, closing as WNF.
28-03-2017

For each new method, depending on system configuration, there is a small number of invocations before which nothing else needs to happen besides counting the invocations, neither checking for overflow nor profiling. Call this number Method::cold_invocation_count(). It is no larger than InterpreterProfileLimit (the point at which MethodData is created), and no larger than various other limits used by MethodCounters, such as Tier0InvokeNotifyFreq. For implementation purposes, we may also assume that this number is smaller than (say) 8 bits wide. This number may be quite small, as low as 200 or 20 or 2. Many methods in the system which are used only for initialization may get run only once or twice, so if we can lazily create MethodCounters and MethodData only after that number of invocations (the "cold invocations"), then we can avoid allocating that extra metadata for all of those methods run only once or a few times. More specifically, while a method is still in its cold invocation count, there is no need to allocate either the MethodData or the MethodCounters. At any point, the MethodCounters *could* be created (based on the current invocation count), but need not be created, if there is an alternative way to store the small invocation count (of 8 bits or less). And this is easy enough to do. Take the MethodCounters pointer (Method::_method_counters) and turn it into a union of MethodCounters* and uintptr_t. Then, note that the two or three low-order bits of that pointer will always be zero if the thing is really a pointer. Use the lowest-order bit as a tag bit to encode that the value is really a short "cold invocation count" (of up to 8 bits), shifted up by one bit position. Then the invocation counter logic will look like this: uintptr_t tem = method->_method_counters; MethodCounters* mc = NULL; if (tem == NULL) { method->_method_counters = method->compute_cold_invocation_count() * 2 + 1; goto invocation_count_increment_done; } else if ((tem&1) != 0) { if (tem >= 3) { method->_method_counters = tem - 2; goto invocation_count_increment_done; } mc = method->inflate_invocation_counters(); } else { mc = (MethodCounters*) tem; // already warm and inflated } ...(work with MethodCounter struct)... invocation_count_increment_done: ...(continue with method entry)... Any path in the interpreter that attempts to update a field of the MethodCounter must first inflate the structure, in case the method is still cold. The inflated counter must be initialized as if it had "been there all along", with its basic invocation count (MethodCounter::_invocation_counter) set to the cold-count. The access method for reading an invocation count from a cold method should behave as if the MethodCounter were already inflated, but does not need to actually perform such an inflation. Inflation should use a CAS instruction to replace the expired cold count (bitwise value 0x0001) with the newly allocated MethodCounters structure. Early inflation (before an expired counter) may be subject to race conditions, where one thread inflates early (non-expired cold count of N*2+1, N > 0) and writes a MethodCounters pointer, while another thread increments the field (to a bitwise value of N*2-1). The net effect will be to leak the MethodCounters structure and drop whatever update was going to be attempted to it. If such structures (created early) are kept on a list, they can be can be validated or cleaned up at any safepoint.
26-02-2016

The runtime code may set MethodCounters but doesn't use MethodData at all, so it's unlikely that we'll have any confidence to change this.
09-03-2015

Handing this RFE back to runtime because it really is runtime.
02-03-2015

We think this something that the compiler team should look at.
10-03-2014

A separate data structure was used for the interpreter counters instead of adding the counters to MethodData, because the MethodData might not have the same life span as the interpreter counters. For example when TieredCompilation is not enabled, the MethodData is not allocated until the interpreter counter reaches the InterpreterProfileLimit. Allocating the MethodData early would waste memory for non-hot methods which only execute a few times. Also the MethodData is only allocated when ProfileInterpreter is enabled, which is the default case for c2 but not for c1. On the other side, when TieredCompilation is enabled the VM does profiling using MethodData and the interpreter counters are not accessed in some cases. Hence allocating the interpreter counters together with the MethodData is not the most memory efficient. The profiling scheme seems complicated with both the interpreter counters and the counters in MethodData. John's comments brought up a very good question. Can the overall profiling method be simplified and the usage of the interpreter counters and MethodData counters be consolidated? It seems to worth investigating on that side.
01-05-2013

Thanks for the suggestions, John. Will look into it.
24-04-2013