Skip to content

Commit

Permalink
Merge pull request #16075 from mpirvu/AOTcachebackground
Browse files Browse the repository at this point in the history
Support for reading/writing a JITServer AOT cache in the background
  • Loading branch information
dsouzai committed Nov 11, 2022
2 parents 531e952 + cabd3ec commit dcca03b
Show file tree
Hide file tree
Showing 9 changed files with 649 additions and 32 deletions.
5 changes: 4 additions & 1 deletion runtime/compiler/control/CompilationThread.cpp
Expand Up @@ -12973,7 +12973,10 @@ TR::CompilationInfo::addOutOfProcessMethodToBeCompiled(JITServer::ServerStream *
{
// Initialize the entry with defaults (some, like methodDetails, are bogus)
TR::IlGeneratorMethodDetails details;
entry->initialize(details, NULL, CP_SYNC_NORMAL, NULL);
// stream == LOAD_AOTCACHE_REQUEST is a special case of request that performs AOTCache loads from disk
// This needs to be served as soon as possible, so we give it a higher priority
CompilationPriority priority = (stream == LOAD_AOTCACHE_REQUEST) ? CP_SYNC_BELOW_MAX : CP_SYNC_NORMAL;
entry->initialize(details, NULL, priority, NULL);
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
{
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
Expand Down
28 changes: 28 additions & 0 deletions runtime/compiler/control/J9Options.cpp
Expand Up @@ -133,6 +133,8 @@ int32_t J9::Options::_sharedROMClassCacheNumPartitions = 16;
int32_t J9::Options::_reconnectWaitTimeMs = 1000;
int32_t J9::Options::_highActiveThreadThreshold = -1;
int32_t J9::Options::_veryHighActiveThreadThreshold = -1;
int32_t J9::Options::_aotCachePersistenceMinDeltaMethods = 200;
int32_t J9::Options::_aotCachePersistenceMinPeriodMs = 10000; // ms
#endif /* defined(J9VM_OPT_JITSERVER) */

#if defined(J9VM_OPT_CRIU_SUPPORT)
Expand Down Expand Up @@ -688,6 +690,12 @@ TR::OptionTable OMR::Options::_feOptions[] = {

{"activeThreadsThresholdForInterpreterSampling=", "M<nnn>\tSampling does not affect invocation count beyond this threshold",
TR::Options::setStaticNumeric, (intptr_t)&TR::Options::_activeThreadsThreshold, 0, "F%d", NOT_IN_SUBSET },
#if defined(J9VM_OPT_JITSERVER)
{"aotCachePersistenceMinDeltaMethods=", "M<nnn>\tnumber of extra AOT methods that need to be added to the JITServer AOT cache before considering a save operation",
TR::Options::setStaticNumeric, (intptr_t)&TR::Options::_aotCachePersistenceMinDeltaMethods, 0, "F%d", NOT_IN_SUBSET },
{"aotCachePersistenceMinPeriodMs=", "M<nnn>\tmiminum time between two consecutive JITServer AOT cache save operations (ms)",
TR::Options::setStaticNumeric, (intptr_t)&TR::Options::_aotCachePersistenceMinPeriodMs, 0, "F%d", NOT_IN_SUBSET },
#endif /* defined(J9VM_OPT_JITSERVER) */
{"aotMethodCompilesThreshold=", "R<nnn>\tIf this many AOT methods are compiled before exceeding aotMethodThreshold, don't stop AOT compiling",
TR::Options::setStaticNumeric, (intptr_t)&TR::Options::_aotMethodCompilesThreshold, 0, "F%d", NOT_IN_SUBSET},
{"aotMethodThreshold=", "R<nnn>\tNumber of methods found in shared cache after which we stop AOTing",
Expand Down Expand Up @@ -2103,6 +2111,26 @@ bool J9::Options::preProcessJitServer(J9JavaVM *vm, J9JITConfig *jitConfig)
{
disabledShareROMClasses = true;
}

// Check if the JITServer AOT cache persistence feature is enabled
const char *xxJITServerAOTCachePersistenceOption = "-XX:+JITServerAOTCachePersistence";
const char *xxDisableJITServerAOTCachePersistenceOption = "-XX:-JITServerAOTCachePersistence";
int32_t xxJITServerAOTCachePersistenceArgIndex = FIND_ARG_IN_VMARGS(EXACT_MATCH, xxJITServerAOTCachePersistenceOption, 0);
int32_t xxDisableJITServerAOTCachePersistenceArgIndex = FIND_ARG_IN_VMARGS(EXACT_MATCH, xxDisableJITServerAOTCachePersistenceOption, 0);
if (xxJITServerAOTCachePersistenceArgIndex > xxDisableJITServerAOTCachePersistenceArgIndex)
{
compInfo->getPersistentInfo()->setJITServerUseAOTCachePersistence(true);

// If enabled, get the name of the directory where the AOT cache files will be stored
const char *xxJITServerAOTCacheDirOption = "-XX:JITServerAOTCacheDir=";
int32_t xxJITServerAOTCacheDirArgIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, xxJITServerAOTCacheDirOption, 0);
if (xxJITServerAOTCacheDirArgIndex >= 0)
{
char *directory = NULL;
GET_OPTION_VALUE(xxJITServerAOTCacheDirArgIndex, '=', &directory);
compInfo->getPersistentInfo()->setJITServerAOTCacheDir(directory);
}
}
}
else // Client mode (possibly)
{
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/control/J9Options.hpp
Expand Up @@ -277,6 +277,8 @@ class OMR_EXTENSIBLE Options : public OMR::OptionsConnector
static int32_t _reconnectWaitTimeMs;
static const uint32_t DEFAULT_JITCLIENT_TIMEOUT = 30000; // ms
static const uint32_t DEFAULT_JITSERVER_TIMEOUT = 30000; // ms
static int32_t _aotCachePersistenceMinDeltaMethods;
static int32_t _aotCachePersistenceMinPeriodMs;
#endif /* defined(J9VM_OPT_JITSERVER) */

#if defined(J9VM_OPT_CRIU_SUPPORT)
Expand Down
33 changes: 33 additions & 0 deletions runtime/compiler/control/JITServerCompilationThread.cpp
Expand Up @@ -215,6 +215,14 @@ outOfProcessCompilationEnd(TR_MethodToBeCompiled *entry, TR::Compilation *comp)
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Failed to serialize AOT method %s", comp->signature());
}
}

// Check whether we need to save a copy of the AOTcache in a file
if (compInfoPT->getCompilationInfo()->getPersistentInfo()->getJITServerUseAOTCachePersistence())
{
auto clientData = comp->getClientData();
if (clientData->usesAOTCache())
clientData->getAOTCache()->triggerAOTCacheStoreToFileIfNeeded();
}
}

TR::CompilationInfoPerThreadRemote::CompilationInfoPerThreadRemote(TR::CompilationInfo &compInfo, J9JITConfig *jitConfig, int32_t id, bool isDiagnosticThread)
Expand Down Expand Up @@ -505,9 +513,34 @@ TR::CompilationInfoPerThreadRemote::processEntry(TR_MethodToBeCompiled &entry, J
entry._compInfoPT = this; // Create the reverse link
// Update the last time the compilation thread had to do something.
compInfo->setLastReqStartTime(compInfo->getPersistentInfo()->getElapsedTime());


if (stream == LOAD_AOTCACHE_REQUEST || stream == SAVE_AOTCACHE_REQUEST)
{
// This is not a true compilation request, but rather a request to save/load an AOTCache to/from file
compInfo->releaseCompMonitor(compThread);
auto aotCacheMap = compInfo->getJITServerAOTCacheMap();
TR_ASSERT(aotCacheMap, "aotCacheMap must exist if such a special request was issued");
if (stream == LOAD_AOTCACHE_REQUEST)
aotCacheMap->loadNextQueuedAOTCacheFromFile(scratchSegmentProvider);
else
aotCacheMap->saveNextQueuedAOTCacheToFile();

// We had the compilation monitor in hand when entering processEntry() and we must leave with it in hand
compInfo->acquireCompMonitor(compThread);

// Put the request back into the pool
setMethodBeingCompiled(NULL); // Must have the compQmonitor
compInfo->recycleCompilationEntry(&entry);
// Will not attempt to suspend this compilation thread.
// If the queue is empty, it will go to sleep waiting for work
return;
}

clearPerCompilationCaches();

_recompilationMethodInfo = NULL;

// Release compMonitor before doing the blocking read
compInfo->releaseCompMonitor(compThread);

Expand Down
10 changes: 9 additions & 1 deletion runtime/compiler/env/J9PersistentInfo.hpp
Expand Up @@ -165,10 +165,12 @@ class PersistentInfo : public OMR::PersistentInfoConnector
_socketTimeoutMs(0),
_clientUID(0),
_JITServerMetricsPort(38500),
_JITServerUseAOTCache(false),
_requireJITServer(false),
_localSyncCompiles(true),
_JITServerUseAOTCache(false),
_JITServerAOTCacheName("default"),
_JITServerUseAOTCachePersistence(false),
_JITServerAOTCacheDir(),
#endif /* defined(J9VM_OPT_JITSERVER) */
OMR::PersistentInfoConnector(pm)
{}
Expand Down Expand Up @@ -357,6 +359,10 @@ class PersistentInfo : public OMR::PersistentInfoConnector
void setJITServerUseAOTCache(bool use) { _JITServerUseAOTCache = use; }
const std::string &getJITServerAOTCacheName() const { return _JITServerAOTCacheName; }
void setJITServerAOTCacheName(const char *name) { _JITServerAOTCacheName = name; }
bool getJITServerUseAOTCachePersistence() const { return _JITServerUseAOTCachePersistence; }
void setJITServerUseAOTCachePersistence(bool use) { _JITServerUseAOTCachePersistence = use; }
const std::string &getJITServerAOTCacheDir() const { return _JITServerAOTCacheDir; }
void setJITServerAOTCacheDir(const char *dir) { _JITServerAOTCacheDir = dir; }
#endif /* defined(J9VM_OPT_JITSERVER) */

private:
Expand Down Expand Up @@ -452,6 +458,8 @@ class PersistentInfo : public OMR::PersistentInfoConnector
bool _localSyncCompiles;
bool _JITServerUseAOTCache;
std::string _JITServerAOTCacheName; // Name of the server AOT cache that this client is using
bool _JITServerUseAOTCachePersistence; // Whether to persist the JITServer AOT caches at the server
std::string _JITServerAOTCacheDir; // Directory where the JITServer persistent AOT caches are located
#endif /* defined(J9VM_OPT_JITSERVER) */
};

Expand Down
10 changes: 8 additions & 2 deletions runtime/compiler/env/PersistentCollections.hpp
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2021 IBM Corp. and others
* Copyright (c) 2018, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand All @@ -23,9 +23,10 @@
#ifndef PERSISTENT_COLLECTIONS_H
#define PERSISTENT_COLLECTIONS_H

#include <vector>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "env/PersistentAllocator.hpp"
#include "env/Region.hpp"
Expand All @@ -36,6 +37,11 @@ using PersistentVectorAllocator = TR::typed_allocator<T, TR::PersistentAllocator
template<typename T>
using PersistentVector = std::vector<T, PersistentVectorAllocator<T>>;

template<typename T>
using PersistentListAllocator = TR::typed_allocator<T, TR::PersistentAllocator &>;
template<typename T>
using PersistentList = std::list<T, PersistentListAllocator<T>>;

template<typename T>
using PersistentUnorderedSetAllocator = TR::typed_allocator<T, TR::PersistentAllocator &>;
template<typename T, typename H = std::hash<T>, typename E = std::equal_to<T>>
Expand Down
26 changes: 18 additions & 8 deletions runtime/compiler/runtime/JITClientSession.cpp
Expand Up @@ -777,16 +777,26 @@ ClientSessionData::getOrCreateAOTCache(JITServer::ServerStream *stream)
{
if (auto aotCacheMap = TR::CompilationInfo::get()->getJITServerAOTCacheMap())
{
auto aotCache = aotCacheMap->get(_aotCacheName, _clientUID);
bool cacheIsBeingLoadedFromDisk = false;
auto aotCache = aotCacheMap->get(_aotCacheName, _clientUID, cacheIsBeingLoadedFromDisk);
if (!aotCache)
{
_vmInfo->_useAOTCache = false;
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"clientUID=%llu requested AOT cache but the AOT cache size limit has been reached, disabling AOT cache",
(unsigned long long)_clientUID
);
return NULL;
if (cacheIsBeingLoadedFromDisk)
{
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"clientUID=%llu requested AOT cache but currently that cache is being loaded from disk", (unsigned long long)_clientUID);
}
else // We cannot create the cache because memory limit is reached
{
_vmInfo->_useAOTCache = false;
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
"clientUID=%llu requested AOT cache but the AOT cache size limit has been reached, disabling AOT cache",
(unsigned long long)_clientUID
);
}
return NULL;
}

auto record = aotCache->getAOTHeaderRecord(&_vmInfo->_aotHeader, _clientUID);
Expand Down

0 comments on commit dcca03b

Please sign in to comment.