openj9 icon indicating copy to clipboard operation
openj9 copied to clipboard

JITServer shared fanin cache

Open mpirvu opened this issue 5 months ago • 0 comments

Fanin data is used by the Inliner to determine from how many different places a callee is invoked. Fanin data is collected by the interpreter profiler and is kept per j9method caller. For each caller we have a linked list of up to 20 entries of <caller, pcIndex, numSamples> (the searching key is <caller, pcIndex>). Currently, the fanin data is serialized and sent to server every time the server creates a j9ResolvedMethod (this happens very often).

This PR proposes to store fanin data at the server in a shared repository (JITServerSharedProfileCache hashtable) that can be accessed by different clients. The 'key' to search for the fanin data of a particular method is a AOTCacheMethodRecord. The 'value' is a ProfiledMethodEntry which includes a FaninProfile. For simplicity, the FaninProfile of a method will include only 3 fields:

class FaninProfile
   {
   uint64_t _numSamples; // Total number of fanin samples for this callee
   uint64_t _numSamplesOtherBucket; // Number of samples falling in the 'otherBucket'
   uint32_t _numCallers; // Number of different callers (max is MAX_IPMETHOD_CALLERS+1)
   };

This simplified view is enough for the Inliner to take appropriate inlining decisions. In a future PR we may eliminate the list of callers that are sent by the client to the server because their identity is not important for performance.

Flow if information:

  1. The server creates a TR_ResolvedJ9JITServerMethod. As part of that process the server sends a message to the client to create a resolved method mirror and the client embeds the fanin info in the reply (serialized info).
  2. The server stores fanin info into the resolved method (with "heap" memory) by using TR_ResolvedJ9JITServerMethod::unpackMethodInfo() which calls iProfiler->cacheFaninDataForMethod()
  3. The server may have two different sources of fanin info: (1) the data sent by the client and (2) the data stored in the shared profile cache The server compares the quality of the data of both sources using JITServerSharedProfileCache::compareFaninProfiles() and picks the source of higher quality. At this point the quality is judged solely based on the total number of samples.
  4. If the shared profile repository has better fanin quality, the server will load that using clientSession->loadFaninDataFromSharedProfileCache();
  5. If the client has better fanin quality, the server deserializes the data from the client with deserializeFaninMethodEntry(), but also stores this information into the shared profile repository: clientSession->storeFaninDataInSharedProfileCache()
  6. If the two fanin sources are about the same in tems of quality, then the server picks the data sent by the client because it is fresher.
  7. At a later point, the Inliner reads the fanin info stored in the J9ResolvedMethod.

Storing the fanin data into the shared profile repository: ClientSessionData::storeFaninDataInSharedProfileCache(TR_OpaqueMethodBlock *method, const TR_ContiguousIPMethodHashTableEntry *serialEntry)

  1. The server converts the incoming j9method into a AOTCacheMethodRecord. To do so, first the server uses the j9method as a key into the _J9MethodMap to find the corresponding J9MethodInfo and from there it returns _aotCacheMethodRecord. If the aotCacheMethodRecord does not yet exist, it will be created by using getClassRecord() and getMethodRecord()
  2. The obtained methodRecord is used as a key into the JITServerSharedProfileCache hashtable to retrieve a ProfiledMethodEntry
  3. If the desired ProfiledMethodEntry exists, the server writes (or overwrites) the fanin data.
  4. If the desired ProfiledMethodEntrydoes not exist, the server creates a new one and writes the fanin data.

Loading the fanin data from the shared profile repository: ClientSessionData::loadFaninDataFromSharedProfileCache(TR_OpaqueMethodBlock *method, TR_Memory *trMemory)

  1. The server converts the incoming j9method into a AOTCacheMethodRecord (see details in the storing procedure)
  2. The obtained methodRecord is used as a key into the JITServerSharedProfileCache hashtable to retrieve a ProfiledMethodEntry
  3. If the cached fanin exists, the server use "heap" memory to allocate a TR_FaninSummaryInfo structure which be returned to the caller to be stored in the J9ResolvedMethod. If the cached fanin does not exist, the server returns a NULL pointer.

mpirvu avatar Jun 16 '25 18:06 mpirvu