-
Notifications
You must be signed in to change notification settings - Fork 713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stored the ram classes before sending the compilationReq to server #9955
Conversation
@mpirvu Can you please review my PR? Thank you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some inline comments
@@ -1227,6 +1229,7 @@ class CompilationInfo | |||
|
|||
#if defined(J9VM_OPT_JITSERVER) | |||
ClientSessionHT *_clientSessionHT; // JITServer hashtable that holds session information about JITClients | |||
PersistentUnorderedMap<J9ROMClass*, JITServerHelpers::ClassInfoTuple> _romJ9ClassMap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need ClassInfoTuple
? Maybe all we need here is an unordered_set
instead of an unordered_map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add some comments with the purpose of this hashtable.
@@ -3146,6 +3146,22 @@ remoteCompile( | |||
if (compiler->isOptServer()) | |||
compiler->setOption(TR_Server); | |||
auto classInfoTuple = JITServerHelpers::packRemoteROMClassInfo(clazz, compiler->fej9vm()->vmThread(), compiler->trMemory()); | |||
|
|||
// check if the romClass is in the map, if it is not insert in the map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer multi-line comments to be capitalized --> Check
{ | ||
// send an empty string instead of the rom class | ||
// send_compile_request_without_romclass | ||
std::get<0>(classInfoTuple) = " "; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can optimize this path because we seem to serialize the ROMClass information and then throw it away
@@ -528,8 +528,13 @@ TR::CompilationInfoPerThreadRemote::processEntry(TR_MethodToBeCompiled &entry, J | |||
J9ROMClass *romClass = NULL; | |||
if (!(romClass = JITServerHelpers::getRemoteROMClassIfCached(clientSession, clazz))) | |||
{ | |||
romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), compInfo->persistentMemory()); | |||
JITServerHelpers::cacheRemoteROMClass(getClientData(), clazz, romClass, &classInfoTuple); | |||
//check whether the first argument of the classInfoTuple is an empty string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The the ROMClass is not already cached at the server we get the information from the request sent by the client and cache it. If the client did not send us anything, the server needs to specifically ask about the information, because it cannot continue with the ROMClas.
16940d8
to
7024052
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few observations. Also I need to think what should happen in the presence of class unloading.
@@ -44,7 +44,7 @@ | |||
#include "vmaccess.h" | |||
|
|||
extern TR::Monitor *assumptionTableMutex; | |||
|
|||
bool serializeClass = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This global can create problems with multithreading.
Please define a local as close as possible to the usage.
@@ -1171,7 +1171,8 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes | |||
case MessageType::ResolvedMethod_getRemoteROMClassAndMethods: | |||
{ | |||
J9Class *clazz = std::get<0>(client->getRecvData<J9Class *>()); | |||
client->write(response, JITServerHelpers::packRemoteROMClassInfo(clazz, fe->vmThread(), trMemory)); | |||
serializeClass = true; | |||
client->write(response, JITServerHelpers::packRemoteROMClassInfo(clazz, fe->vmThread(), trMemory, serializeClass)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you don't need serializeClass
; instead you can pass directly true
@@ -298,6 +298,7 @@ TR::CompilationInfoPerThreadRemote::processEntry(TR_MethodToBeCompiled &entry, J | |||
bool abortCompilation = false; | |||
uint64_t clientId = 0; | |||
TR::CompilationInfo *compInfo = getCompilationInfo(); | |||
auto comp = getCompilation(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comp object does not exist at this point. Most likely comp == NULL
at this point
// It could be a renewed connection, so that's a new server because old one was shutdown | ||
// When the server receives an empty ROM class it would check if it actually has this class cached, | ||
// And if it it's not cached, send a request to the client | ||
romClass = JITServerHelpers::getRemoteROMClass(clazz, stream, comp->trMemory(), &classInfoTuple); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, because comp
is likely NULL
you cannot use comp->trMemory()
. However, looking at the definition of getRemoteROMClass()
the only reason it needs trMemory
is for trMemory->trPersistentMemory()
which you can obtain from compInfo->persistentMemory()
as used above. So you need to modify getRemoteROMClass()
to accept persistentMemory
as a parameter.
JITServerHelpers::cacheRemoteROMClass(getClientData(), clazz, romClass, &classInfoTuple); | ||
// Check whether the first argument of the classInfoTuple is an empty string | ||
// If it's an empty string then I dont't need to cache it | ||
if(std::get<0>(classInfoTuple) != " ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not empty string, but rather a string with one character. You can actually create an empty string by calling the default constructor and test it with string.empty() function
@@ -324,7 +333,7 @@ JITServerHelpers::packRemoteROMClassInfo(J9Class *clazz, J9VMThread *vmThread, T | |||
uintptr_t classChainOffsetOfIdentifyingLoaderForClazz = fe->sharedCache() ? | |||
fe->sharedCache()->getClassChainOffsetOfIdentifyingLoaderForClazzInSharedCacheNoFail((TR_OpaqueClassBlock *)clazz) : 0; | |||
|
|||
return std::make_tuple(packROMClass(clazz->romClass, trMemory), methodsOfClass, baseClass, numDims, parentClass, | |||
return std::make_tuple(packROMClass(clazz->romClass, trMemory, serializeClass), methodsOfClass, baseClass, numDims, parentClass, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to pass serializeClass
to packROMClass
. Instead you could do:
return std::make_tuple(serializeClass ? packROMClass(clazz->romClass, trMemory) : std::string(), methodsOfClass, baseClass, numDims, parentClass,
I have a concern that's similar to class unloading. @mpirvu I think we could just look at the list of unloaded classes at the client and delete them from the |
I thought about deleting the RomClass from the local set at the client on class unloading. I guess I was trying to over-optimize because one ROMClass can be used by several RAMClasses (with different classloaders) and even if a RAMClass may die the ROMClass can still exist. |
In
We just need to augment the code with some lines that would delete the corresponding j9class from our set. Since class unloading is done in a stop-the-world fashion (only one thread is active), acquiring a monitor is not needed. |
7c09331
to
cb6c0f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some inline comments. Also, you need to increment the minor version for the CommunicationStream because we changed the content of the messages.
@@ -1009,6 +1010,7 @@ class CompilationInfo | |||
} | |||
void setNewlyExtendedClasses(PersistentUnorderedMap<TR_OpaqueClassBlock*, uint8_t> *it) { _newlyExtendedClasses = it; } | |||
|
|||
TR::Monitor *getRamSetMonitor() const { return _ramSetMonitor; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name RamSet
is not very descriptive.
I am not feeling very inspired, but maybe something along the lines classesCachedAtServerMonitor
better depicts what this monitor is used for
@@ -2115,6 +2115,12 @@ static void jitHookClassUnload(J9HookInterface * * hookInterface, UDATA eventNum | |||
// Add to JITServer unload list | |||
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) | |||
compInfo->getUnloadedClassesTempList()->push_back(clazz); | |||
// Loop through the set to find the class that needs to be purged once found erase from the set | |||
auto it = compInfo->getRamJ9ClassSet().find(unloadedEvent->clazz); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code should be put under the if
that determines we are running on the client.
auto it = compInfo->getRamJ9ClassSet().find(unloadedEvent->clazz); | ||
if (it != compInfo->getRamJ9ClassSet().end()) | ||
{ | ||
compInfo->getRamJ9ClassSet().erase(it); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can try to erase it even if it does not exist, thus avoiding one search operation when desired item exists in the collection.
OMR::CriticalSection romClassCache(compInfo->getRamSetMonitor()); | ||
if (compInfo->getRamJ9ClassSet().find(clazz) == compInfo->getRamJ9ClassSet().end()) | ||
{ | ||
// clazz was not found send the romclass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is composed from two sentences. Let make that obvious: "clazz not found. Send the romClass to JITServer."
{ | ||
// Send an empty string instead of the rom class, first don't serialize the ROMClass | ||
// Send_compile_request_without_romclass | ||
serializeClass = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The else
part is not needed, because serializeClass
starts as false
// When the server receives an empty ROM class it would check if it actually has this class cached, | ||
// And if it it's not cached, send a request to the client | ||
romClass = JITServerHelpers::getRemoteROMClass(clazz, stream, compInfo->persistentMemory(), &classInfoTuple); | ||
JITServerHelpers::cacheRemoteROMClass(getClientData(), clazz, romClass, &classInfoTuple); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The line JITServerHelpers::cacheRemoteROMClass(getClientData(), clazz, romClass, &classInfoTuple);
is common for if
and else
part so it can be taken out and placed after the if-then-else
@@ -350,6 +350,15 @@ JITServerHelpers::getRemoteROMClass(J9Class *clazz, JITServer::ServerStream *str | |||
return romClassFromString(std::get<0>(*classInfoTuple), trMemory->trPersistentMemory()); | |||
} | |||
|
|||
J9ROMClass * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the previous version of JITServerHelpers::getRemoteClass()
needed anymore? If not, we can delete it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it's used in getAndCacheRemoteROMClass()
in CompilationThread.cpp
and getAndCacheRemoteROMClass
is used in other several files. That's why I overloaded the function. For example, here _romClass = threadCompInfo->getAndCacheRemoteROMClass(_ramClass, trMemory);
which is in j9methodServer.cpp.
@@ -1227,6 +1230,8 @@ class CompilationInfo | |||
|
|||
#if defined(J9VM_OPT_JITSERVER) | |||
ClientSessionHT *_clientSessionHT; // JITServer hashtable that holds session information about JITClients | |||
PersistentUnorderedSet<J9Class*> _ramJ9ClassSet; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment here about the _ramJ9ClassSet
. Maybe replace with _classesCachedAtServer
@@ -2115,6 +2115,12 @@ static void jitHookClassUnload(J9HookInterface * * hookInterface, UDATA eventNum | |||
// Add to JITServer unload list | |||
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) | |||
compInfo->getUnloadedClassesTempList()->push_back(clazz); | |||
// Loop through the set to find the class that needs to be purged once found erase from the set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment seems to be composed of two sentences, so let's make that clear:
// Loop through the set to find the class that needs to be purged.
// Once found erase from the set.
@@ -3145,7 +3144,28 @@ remoteCompile( | |||
|
|||
if (compiler->isOptServer()) | |||
compiler->setOption(TR_Server); | |||
auto classInfoTuple = JITServerHelpers::packRemoteROMClassInfo(clazz, compiler->fej9vm()->vmThread(), compiler->trMemory()); | |||
|
|||
// Check if the Clazz is in the set, if it is not insert in the set |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Transform this comment into:
Check the _classesCachedAtServer set to determine whether JITServer is likely to have this class already cached.
If so, do not send the ROMClass content to save network traffic."
cb6c0f4
to
ab8f015
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
jenkins test sanity plinuxjit,xlinuxjit jdk11 |
It just occurred to me that in cases where the server clears its internal caches because of a seqNo that is lost we must destroy the set of cached j9classes at the client as well. |
ab8f015
to
be21e04
Compare
@@ -215,6 +215,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes | |||
auto table = (JITClientPersistentCHTable*)comp->getPersistentInfo()->getPersistentCHTable(); | |||
std::string encoded = FlatPersistentClassInfo::serializeHierarchy(table); | |||
|
|||
compInfo->getclassesCachedAtServer().clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This require a mutex.
Maybe it's better to put is after the write
operation so that we don't delay it.
be21e04
to
3e7486a
Compare
I realized that this is missing, so please increment the minor version. |
Stored the ramClasses in an unordered_set before sending the compilation request to the server. I check if the ram class (clazz) is cached in the set. if it is not stored then it will be cached in the set and will send the corresponding ROM by setting the serializeClass bool to true. If the clazz is already in the cache set this means it has already been sent to the server. So send the clazz again but with empty ROM class (empty string for ROM Class) by setting serializeClass bool to false. issue: eclipse-openj9#9708 Signed-off-by: Eman Elsabban <eman.elsaban1@gmail.com>
3e7486a
to
87efa9e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
jenkins test sanity plinuxjit,xlinuxjit jdk11 |
Stored the romClasses in an unordered_map before sending the compilation
request to the server. I also check if the romClass is in the map, if it is
I send an empty string to the server instead of the romClass again and on the server
side I check to see if I received an empty string. If so I don't cache it.
issue: #9708
Signed-off-by: Eman Elsabban eman.elsaban1@gmail.com