Skip to content

Commit

Permalink
Client Request Cached Methods List from JIT Server
Browse files Browse the repository at this point in the history
Added an option that makes the client request a list of cached
methods from the server on bootstrap, and set the count for
those methods as scount to improve rampup

Signed-off-by: Luke Li <[email protected]>
  • Loading branch information
luke-li-2003 committed Oct 16, 2024
1 parent d51176e commit dc57383
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 35 deletions.
87 changes: 87 additions & 0 deletions runtime/compiler/control/HookedByTheJit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/

#include <string>
#include <unordered_set>

#include <algorithm>
#include <limits.h>
#ifdef LINUX
Expand Down Expand Up @@ -385,6 +388,27 @@ static uint32_t initializeSendTargetHelperFuncHashValueForSpreading(J9Method* me

static bool highCodeCacheOccupancyThresholdReached = false;

#if defined(J9VM_OPT_JITSERVER)
static int32_t calculateCountForMethodCachedAtServer(J9ROMMethod * romMethod,
TR::Options * optionsJIT,
TR::Options * optionsAOT)
{
int32_t scount = TR_INITIAL_SCOUNT;
if (optionsAOT)
{
scount = optionsAOT->getInitialSCount();
if ((scount == TR_QUICKSTART_INITIAL_SCOUNT) || (scount == TR_INITIAL_SCOUNT))
{
// If scount is not user specified (coarse way due to info being lost
// from options parsing)
scount= std::min(getCount(romMethod, optionsJIT, optionsAOT),
optionsAOT->getInitialSCount());
}
}
return scount;
}
#endif // J9VM_OPT_JITSERVER

static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)
{
J9VMInitializeSendTargetEvent * event = (J9VMInitializeSendTargetEvent *)eventData;
Expand Down Expand Up @@ -425,6 +449,44 @@ static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum
}
}

#if defined(J9VM_OPT_JITSERVER)
bool methodCachedAtServer = false;
PersistentUnorderedSet<std::string> *serverAOTMethodSet =
(PersistentUnorderedSet<std::string> *) jitConfig->serverAOTMethodSet;

if (serverAOTMethodSet != NULL)
{
// Construct a signature
J9UTF8 *className;
J9UTF8 *name;
J9UTF8 *signature;
getClassNameSignatureFromMethod(method, className, name, signature);
// SigLen calculation as used in TRJ9VMBase::printTruncatedSignature
int32_t sigLen = J9UTF8_LENGTH(className) + J9UTF8_LENGTH(name) +
J9UTF8_LENGTH(signature) + 2;

if (sigLen < 1024)
{
char sigC[1024];
sigLen = sprintf(sigC, "%.*s.%.*s%.*s",
J9UTF8_LENGTH(className), utf8Data(className),
J9UTF8_LENGTH(name), utf8Data(name),
J9UTF8_LENGTH(signature), utf8Data(signature));

// contains
methodCachedAtServer =
(serverAOTMethodSet->find(std::string(sigC)) != serverAOTMethodSet->end());

if (TR::Options::getVerboseOption(TR_VerboseJITServer)
&& TR::Options::getVerboseOption(TR_VerboseCounts))
if (methodCachedAtServer)
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"Method %s was cached at the server",
sigC);
}
}
#endif // J9VM_OPT_JITSERVER

if (TR::Options::getAOTCmdLineOptions()->anOptionSetContainsACountValue())
{
TR::OptionSet * optionSet = findOptionSet(method, true);
Expand Down Expand Up @@ -628,6 +690,21 @@ static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum
}
#endif // defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
} // if (TR::Options::sharedClassCache())

#if defined(J9VM_OPT_JITSERVER)
// If the method is cached at the server side, set the count to the lower number
// regardless of whether the count has been set before
if (methodCachedAtServer)
{
int32_t serverCount =
calculateCountForMethodCachedAtServer(romMethod, optionsJIT, optionsAOT);
if (count == -1)
count = serverCount;
else
count = std::min(count, serverCount);
}
#endif // J9VM_OPT_JITSERVER

if (count == -1) // count didn't change yet
{
if (!TR::Options::getCountsAreProvidedByUser() &&
Expand Down Expand Up @@ -4181,6 +4258,16 @@ void JitShutdown(J9JITConfig * jitConfig)

TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);

#if defined(J9VM_OPT_JITSERVER)
PersistentUnorderedSet<std::string> *serverAOTMethodSet =
(PersistentUnorderedSet<std::string> *) jitConfig->serverAOTMethodSet;
if (serverAOTMethodSet)
{
serverAOTMethodSet->~unordered_set();
TR_Memory::jitPersistentFree((void *)serverAOTMethodSet);
}
#endif // J9VM_OPT_JITSERVER

#if defined(J9VM_OPT_CRIU_SUPPORT)
if (jitConfig->javaVM->internalVMFunctions->isCRaCorCRIUSupportEnabled(jitConfig->javaVM))
{
Expand Down
79 changes: 76 additions & 3 deletions runtime/compiler/control/JITServerCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/

#include <string.h>

#include "control/JITServerCompilationThread.hpp"

#include "codegen/CodeGenerator.hpp"
Expand Down Expand Up @@ -202,9 +204,14 @@ outOfProcessCompilationEnd(TR_MethodToBeCompiled *entry, TR::Compilation *comp)
CachedAOTMethod *freshMethodRecord = NULL;
if (!methodRecord)
{
freshMethodRecord = CachedAOTMethod::create(compInfoPT->getDefiningClassChainRecord(), compInfoPT->getMethodIndex(),
entry->_optimizationPlan->getOptLevel(), clientData->getAOTHeaderRecord(),
comp->getSerializationRecords(), codeCacheHeader, codeSize, dataCacheHeader, dataSize);
freshMethodRecord = CachedAOTMethod::create(compInfoPT->getDefiningClassChainRecord(),
compInfoPT->getMethodIndex(),
entry->_optimizationPlan->getOptLevel(),
clientData->getAOTHeaderRecord(),
comp->getSerializationRecords(),
codeCacheHeader, codeSize,
dataCacheHeader, dataSize,
comp->signature());
methodRecord = freshMethodRecord;
}

Expand Down Expand Up @@ -1101,6 +1108,72 @@ TR::CompilationInfoPerThreadRemote::processEntry(TR_MethodToBeCompiled &entry, J
stream->writeError(compilationLowPhysicalMemory, (uint64_t) computeServerMemoryState(getCompilationInfo()));
abortCompilation = true;
}
catch (const JITServer::StreamAotCacheMapRequest &e)
{
const std::string& aotCacheName = e.getCacheName();

if (TR::Options::getVerboseOption(TR_VerboseJITServer))
{
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"compThreadID=%d handling request for AOT cache %s method list",
getCompThreadId(), aotCacheName.c_str());
}

auto aotCacheMap = compInfo->getJITServerAOTCacheMap();

// If the cache exists but is not loaded, get() will set
// pending to True and return NULL for aotCache;
// we treat this NULL as a failure like any other NULL
bool pending = false;
auto aotCache = aotCacheMap->get(aotCacheName, 0, pending);

std::vector<std::string> methodSignaturesV;
if (aotCache)
{
auto cachedMethodMonitor = aotCache->getCachedMethodMonitor();
try
{
{
OMR::CriticalSection cs(cachedMethodMonitor);

auto cachedAOTMethod = aotCache->getCachedMethodHead();
methodSignaturesV.reserve(aotCache->getCachedMethodMap().size());

for (;cachedAOTMethod != NULL;
cachedAOTMethod = cachedAOTMethod->getNextRecord())
{
const SerializedAOTMethod &serializedAOTMethod = cachedAOTMethod->data();
methodSignaturesV.push_back(std::string(serializedAOTMethod.signature()));
}
}
}
catch (const std::bad_alloc &e)
{
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,
"std::bad_alloc: %s",
e.what());
}

if (TR::Options::getVerboseOption(TR_VerboseJITServer))
{
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"Sending the list of AOT methods size %d",
methodSignaturesV.size());
}
}
else // Failed getting aotCache, treat pending as a failure
{
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
{
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Failed getting aotCache");
}
}
stream->write(JITServer::MessageType::AOTCacheMap_reply, methodSignaturesV);

abortCompilation = true;
deleteStream = true;
}

// Acquire VM access
//
Expand Down
121 changes: 121 additions & 0 deletions runtime/compiler/control/rossa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include <stdlib.h>
#include <string.h>

#include <vector>
#include <string>

#ifdef WINDOWS
// Undefine the winsockapi because winsock2 defines it. Removes warnings.
#if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
Expand Down Expand Up @@ -1921,6 +1924,83 @@ onLoadInternal(
return 0;
}

#if defined(J9VM_OPT_JITSERVER)
static int32_t J9THREAD_PROC fetchServerCachedAOTMethods(void * entryarg)
{
J9JITConfig *jitConfig = (J9JITConfig *) entryarg;
J9JavaVM *vm = jitConfig->javaVM;
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();

j9thread_t osThread = (j9thread_t) jitConfig->serverAOTQueryThread;
J9VMThread *vmThread = NULL;

int rc = vm->internalVMFunctions->internalAttachCurrentThread(vm, &vmThread, NULL,
J9_PRIVATE_FLAGS_DAEMON_THREAD | J9_PRIVATE_FLAGS_NO_OBJECT |
J9_PRIVATE_FLAGS_SYSTEM_THREAD | J9_PRIVATE_FLAGS_ATTACHED_THREAD,
osThread);

if (rc != JNI_OK)
{
return rc;
}

try
{
JITServer::ClientStream *client = new (PERSISTENT_NEW) JITServer::ClientStream(persistentInfo);
client->write(JITServer::MessageType::AOTCacheMap_request,
persistentInfo->getJITServerAOTCacheName());

client->read();
auto result = client->getRecvData<std::vector<std::string>>();

std::vector<std::string> &cachedMethods = std::get<0>(result);

if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Received %d methods",
cachedMethods.size());

PersistentUnorderedSet<std::string> *serverAOTMethodSet =
new (PERSISTENT_NEW) PersistentUnorderedSet<std::string>(
PersistentUnorderedSet<std::string>::allocator_type
(TR::Compiler->persistentAllocator()));

for (const auto &methodSig : cachedMethods)
{
serverAOTMethodSet->insert(methodSig);
}

client->~ClientStream();
TR_Memory::jitPersistentFree(client);

FLUSH_MEMORY(TR::Compiler->target.isSMP());
jitConfig->serverAOTMethodSet = (void *) serverAOTMethodSet;
}
catch (const JITServer::StreamFailure &e)
{
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJITServer, TR_VerboseCompilationDispatch))
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,
"JITServer::StreamFailure: %s",
e.what());

JITServerHelpers::postStreamFailure(
OMRPORT_FROM_J9PORT(vm->portLibrary),
compInfo, e.retryConnectionImmediately(), true);
}
catch (const std::bad_alloc &e)
{
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJITServer, TR_VerboseCompilationDispatch))
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,
"std::bad_alloc: %s",
e.what());
}

vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);
j9thread_exit(NULL);

return 0;
}
#endif // J9VM_OPT_JITSERVER

extern "C" int32_t
aboutToBootstrap(J9JavaVM * javaVM, J9JITConfig * jitConfig)
Expand Down Expand Up @@ -2191,6 +2271,47 @@ aboutToBootstrap(J9JavaVM * javaVM, J9JITConfig * jitConfig)
UT_MODULE_LOADED(J9_UTINTERFACE_FROM_VM(javaVM));
Trc_JIT_VMInitStages_Event1(curThread);
Trc_JIT_portableSharedCache_enabled_or_disabled(curThread, J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE) ? 1 : 0);

#if defined(J9VM_OPT_JITSERVER)
if (!persistentInfo->getJITServerUseAOTCache())
{
TR::Options::getCmdLineOptions()->setOption(TR_RequestJITServerCachedMethods, false);
}

jitConfig->serverAOTMethodSet = NULL;
if (TR::Options::getCmdLineOptions()->getOption(TR_RequestJITServerCachedMethods))
{
// Ask the server for its cached methods
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
{
if (JITServerHelpers::isServerAvailable())
{
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"Creating a thread to ask the server for its cached methods");

IDATA result = javaVM->internalVMFunctions->createThreadWithCategory(
(omrthread_t *) &(jitConfig->serverAOTQueryThread),
javaVM->defaultOSStackSize,
J9THREAD_PRIORITY_NORMAL,
0,
&fetchServerCachedAOTMethods,
(void *) jitConfig,
J9THREAD_CATEGORY_SYSTEM_JIT_THREAD
);

if (result != J9THREAD_SUCCESS)
{
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"Query thread not created");
}
}
}
}
#endif // J9VM_OPT_JITSERVER


return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/net/CommunicationStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class CommunicationStream
// likely to lose an increment when merging/rebasing/etc.
//
static const uint8_t MAJOR_NUMBER = 1;
static const uint16_t MINOR_NUMBER = 68; // ID: +/QzEedP8cjGovxgYECy
static const uint16_t MINOR_NUMBER = 69; // ID: zhVsTX9SmmM39Qf52qpp
static const uint8_t PATCH_NUMBER = 0;
static uint32_t CONFIGURATION_FLAGS;

Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/net/MessageTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ const char *messageNames[] =
"KnownObjectTable_getReferenceField",
"KnownObjectTable_getKnownObjectTableDumpInfo",
"AOTCache_getROMClassBatch",
"AOTCacheMap_request",
"AOTCacheMap_reply"
};

static_assert(sizeof(messageNames) / sizeof(messageNames[0]) == MessageType_MAXTYPE,
Expand Down
3 changes: 3 additions & 0 deletions runtime/compiler/net/MessageTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ enum MessageType : uint16_t

AOTCache_getROMClassBatch,

AOTCacheMap_request,
AOTCacheMap_reply,

MessageType_MAXTYPE
};
extern const char *messageNames[];
Expand Down
Loading

0 comments on commit dc57383

Please sign in to comment.