Skip to content

Commit f3dc638

Browse files
authored
Merge pull request #19808 from cjjdespres/disclaim-free-message-buffer
Use custom allocator for JITServer client MessageBuffers
2 parents d946965 + 5c98d28 commit f3dc638

File tree

6 files changed

+104
-12
lines changed

6 files changed

+104
-12
lines changed

runtime/compiler/control/HookedByTheJit.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5320,6 +5320,11 @@ static void jitStateLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInf
53205320
static char *disableIdleRATCleanup = feGetEnv("TR_disableIdleRATCleanup");
53215321
if (disableIdleRATCleanup == NULL)
53225322
persistentInfo->getRuntimeAssumptionTable()->reclaimMarkedAssumptionsFromRAT(-1);
5323+
5324+
#if defined(J9VM_OPT_JITSERVER)
5325+
if (compInfo->getMethodQueueSize() == 0)
5326+
JITServer::MessageBuffer::tryFreePersistentAllocator();
5327+
#endif /* defined(J9VM_OPT_JITSERVER) */
53235328
}
53245329

53255330
// Logic related to IdleCPU exploitation

runtime/compiler/control/rossa.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,6 +1792,9 @@ onLoadInternal(
17921792
}
17931793
}
17941794

1795+
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::NONE)
1796+
JITServer::MessageBuffer::initTotalBuffersMonitor();
1797+
17951798
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
17961799
{
17971800
JITServer::CommunicationStream::initConfigurationFlags();

runtime/compiler/env/PersistentAllocator.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,21 @@ PersistentAllocator::disclaimAllSegments()
757757
#endif // LINUX
758758
return numSegDisclaimed;
759759
}
760+
761+
void
762+
TR::PersistentAllocator::adviseDontNeedSegments()
763+
{
764+
#ifdef LINUX
765+
j9thread_monitor_enter(_segmentMonitor);
766+
for (auto segmentIterator = _segments.begin(); segmentIterator != _segments.end(); ++segmentIterator)
767+
{
768+
J9MemorySegment &segment = *segmentIterator;
769+
size_t segLength = segment.heapTop - segment.heapBase;
770+
madvise(segment.heapBase, segLength, MADV_DONTNEED);
771+
}
772+
j9thread_monitor_exit(_segmentMonitor);
773+
#endif
774+
}
760775
} // namespace J9
761776

762777
void *

runtime/compiler/env/PersistentAllocator.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ class PersistentAllocator
7777
int disclaimAllSegments();
7878
int getNumSegments() const { return _numSegments; }
7979

80+
// Issue MADV_DONTNEED on the segments allocated by this allocator. This has the effect
81+
// of zeroing out that memory if it has no persistent backing (see madvise(2)), so you must
82+
// be sure that these segments are not actually in use in that case.
83+
void adviseDontNeedSegments();
84+
8085
private:
8186

8287
// Persistent block header

runtime/compiler/net/MessageBuffer.cpp

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,53 @@
2121
*******************************************************************************/
2222

2323
#include "net/MessageBuffer.hpp"
24+
#include "infra/CriticalSection.hpp"
25+
#include "env/VerboseLog.hpp"
26+
#include "control/Options.hpp"
2427
#include <cstring>
2528

2629
namespace JITServer
2730
{
31+
32+
TR::Monitor *MessageBuffer::_totalBuffersMonitor = NULL;
33+
int MessageBuffer::_totalBuffers = 0;
34+
TR::PersistentAllocator *MessageBuffer::_allocator = NULL;
35+
2836
MessageBuffer::MessageBuffer() :
29-
_capacity(INITIAL_BUFFER_SIZE),
30-
_allocator(TR::Compiler->persistentGlobalAllocator())
37+
_capacity(INITIAL_BUFFER_SIZE)
3138
{
39+
OMR::CriticalSection cs(getTotalBuffersMonitor());
40+
41+
if (!_allocator)
42+
{
43+
if (J9::PersistentInfo::_remoteCompilationMode == JITServer::CLIENT)
44+
{
45+
uint32_t memoryType = MEMORY_TYPE_VIRTUAL; // Force the usage of mmap for allocation
46+
TR::PersistentAllocatorKit kit(1 << 20/*1 MB*/, *TR::Compiler->javaVM, memoryType);
47+
_allocator = new (TR::Compiler->rawAllocator) TR::PersistentAllocator(kit);
48+
}
49+
else
50+
{
51+
_allocator = &TR::Compiler->persistentGlobalAllocator();
52+
}
53+
}
54+
3255
_storage = allocateMemory(_capacity);
3356
if (!_storage)
3457
throw std::bad_alloc();
3558
_curPtr = _storage;
59+
_totalBuffers++;
60+
}
61+
62+
MessageBuffer::~MessageBuffer()
63+
{
64+
OMR::CriticalSection cs(getTotalBuffersMonitor());
65+
66+
freeMemory(_storage);
67+
_totalBuffers--;
68+
69+
if ((0 == _totalBuffers) && (J9::PersistentInfo::_remoteCompilationMode == JITServer::CLIENT))
70+
_allocator->adviseDontNeedSegments();
3671
}
3772

3873
void
@@ -79,7 +114,7 @@ MessageBuffer::writeData(const void *dataStart, uint32_t dataSize, uint8_t paddi
79114
_curPtr += dataSize + paddingSize;
80115
return offset(data);
81116
}
82-
117+
83118
uint8_t
84119
MessageBuffer::alignCurrentPositionOn64Bit()
85120
{
@@ -108,5 +143,22 @@ MessageBuffer::computeRequiredCapacity(uint32_t requiredSize)
108143
extendedCapacity *= 2;
109144
return extendedCapacity;
110145
}
111-
};
112146

147+
void
148+
MessageBuffer::tryFreePersistentAllocator()
149+
{
150+
if (J9::PersistentInfo::_remoteCompilationMode != JITServer::CLIENT)
151+
return;
152+
153+
OMR::CriticalSection cs(getTotalBuffersMonitor());
154+
155+
if ((_totalBuffers != 0) || (_allocator == NULL))
156+
return;
157+
158+
_allocator->~PersistentAllocator();
159+
TR::Compiler->rawAllocator.deallocate(_allocator);
160+
_allocator = NULL;
161+
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
162+
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Freed message buffer storage allocator");
163+
}
164+
};

runtime/compiler/net/MessageBuffer.hpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "env/TRMemory.hpp"
2828
#include "OMR/Bytes.hpp" // for alignNoCheck
2929
#include "env/CompilerEnv.hpp"
30+
#include "infra/Monitor.hpp"
3031

3132
namespace JITServer
3233
{
@@ -45,16 +46,17 @@ namespace JITServer
4546
4647
Variable _curPtr defines the boundary of the current data. Reading/writing to/from buffer
4748
will always advance the pointer.
49+
50+
A shared, reference-counted persistent allocator is used for all message buffers at a JITServer client.
51+
The freed persistent memory tracked by the allocator is disclaimed when the last MessageBuffer is destroyed,
52+
and the allocator itself can be destroyed with tryFreePersistentAllocator() if there are no active connections
53+
to a server. Servers use the persistent global allocator.
4854
*/
4955
class MessageBuffer
5056
{
5157
public:
5258
MessageBuffer();
53-
54-
~MessageBuffer()
55-
{
56-
freeMemory(_storage);
57-
}
59+
~MessageBuffer();
5860

5961

6062
/**
@@ -204,18 +206,28 @@ class MessageBuffer
204206

205207
uint32_t getCapacity() const { return _capacity; }
206208

209+
// Must be called before any client-server communication takes place
210+
static void initTotalBuffersMonitor() { _totalBuffersMonitor = TR::Monitor::create("JIT-JITServerTotalBuffersMonitor"); }
211+
212+
// Try to free the custom persistent allocator for message buffers. This method does nothing
213+
// if the JVM is not in client mode, or if there is at least one active message buffer.
214+
static void tryFreePersistentAllocator();
207215

208216
private:
209217
static const size_t INITIAL_BUFFER_SIZE = 32768; // Initial buffer size is 32K
210218
uint32_t offset(char *addr) const { return addr - _storage; }
211-
char *allocateMemory(uint32_t capacity) { return static_cast<char *>(_allocator.allocate(capacity)); }
212-
void freeMemory(char *storage) { _allocator.deallocate(storage); }
219+
char *allocateMemory(uint32_t capacity) { return static_cast<char *>(_allocator->allocate(capacity)); }
220+
void freeMemory(char *storage) { _allocator->deallocate(storage); }
213221
uint32_t computeRequiredCapacity(uint32_t requiredSize);
222+
static TR::Monitor *getTotalBuffersMonitor() { return _totalBuffersMonitor; }
214223

215224
uint32_t _capacity;
216225
char *_storage;
217226
char *_curPtr;
218-
TR::PersistentAllocator &_allocator;
227+
228+
static TR::Monitor *_totalBuffersMonitor;
229+
static int _totalBuffers;
230+
static TR::PersistentAllocator *_allocator;
219231
};
220232
};
221233
#endif

0 commit comments

Comments
 (0)