Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ CONFIG_DWORD_INFO(INTERNAL_ContinueOnAssert, W("ContinueOnAssert"), 0, "If set,
CONFIG_DWORD_INFO(INTERNAL_InjectFatalError, W("InjectFatalError"), 0, "")
CONFIG_DWORD_INFO(INTERNAL_InjectFault, W("InjectFault"), 0, "")
CONFIG_DWORD_INFO(INTERNAL_SuppressChecks, W("SuppressChecks"),0, "")

// If we manage to reserve the initial memory close to coreclr we might get a better performance
// but it's better to turn it off when we run benchmarks for more stable results (always reserve far from coreclr)
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ReserveInitialMemoryNearClr, W("UNSUPPORTED_DontReserveInitialMemoryNearClr"), 0, "Don't try to reserve the initial memory close to coreclr")
#ifdef FEATURE_EH_FUNCLETS
CONFIG_DWORD_INFO(INTERNAL_SuppressLockViolationsOnReentryFromOS, W("SuppressLockViolationsOnReentryFromOS"), 0, "64 bit OOM tests re-enter the CLR via RtlVirtualUnwind. This indicates whether to suppress resulting locking violations.")
#endif // FEATURE_EH_FUNCLETS
Expand Down
11 changes: 9 additions & 2 deletions src/coreclr/pal/src/include/pal/virtual.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,24 @@ class ExecutableMemoryAllocator
int32_t GenerateRandomStartOffset();

private:

// There does not seem to be an easy way find the size of a library on Unix.
// So this constant represents an approximation of the libcoreclr size (on debug build)
// So this constant represents an approximation of the libcoreclr size
// that can be used to calculate an approximate location of the memory that
// is in 2GB range from the coreclr library. In addition, having precise size of libcoreclr
// is not necessary for the calculations.
static const int32_t CoreClrLibrarySize = 100 * 1024 * 1024;
static const int32_t CoreClrLibrarySize = 16 * 1024 * 1024;

#ifdef TARGET_XARCH
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ifdef is incorrect, we don't define TARGET_XARCH out of JIT. Can you please use
#if defined(TARGET_ARM) || defined(TARGET_ARM64) here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, again I am using JIT's flags in the VM 😞 the incorrect define slightly regressed x64/x86 by decreasing preferable size from 2Gb to 1Gb. Thanks, fixed

// This constant represent the max size of the virtual memory that this allocator
// will try to reserve during initialization. We want all JIT-ed code and the
// entire libcoreclr to be located in a 2GB range.
static const int32_t MaxExecutableMemorySize = 0x7FFF0000;
#else
// It seems to be more difficult to reserve a 2Gb chunk on arm so we'll try smaller one
static const int32_t MaxExecutableMemorySize = 768 * 1024 * 1024;
#endif

static const int32_t MaxExecutableMemorySizeNearCoreClr = MaxExecutableMemorySize - CoreClrLibrarySize;

// Start address of the reserved virtual address space
Expand Down
27 changes: 22 additions & 5 deletions src/coreclr/pal/src/map/virtual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); // some headers have code with asserts, so d
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <clrconfignocache.h>

#if HAVE_VM_ALLOCATE
#include <mach/vm_map.h>
Expand Down Expand Up @@ -2140,7 +2141,17 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory()
int32_t preferredStartAddressIncrement;
UINT_PTR preferredStartAddress;
UINT_PTR coreclrLoadAddress;
const int32_t MemoryProbingIncrement = 128 * 1024 * 1024;

#if TARGET_XARCH
const int32_t AddressProbingIncrement = 128 * 1024 * 1024;
const int32_t AllocSizeProbingDecrement = 128 * 1024 * 1024;
#else
// Smaller steps on ARM becuase we try hard finding a spare memory in a 128Mb
// distance from coreclr so e.g. all calls from corelib to coreclr could use relocs
const int32_t AddressProbingIncrement = 8 * 1024 * 1024;
const int32_t AllocSizeProbingDecrement = 64 * 1024 * 1024;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the increment and decrement differ for arm?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unified (and increased the initial size to 1Gb) - works pretty good on my Apple M1 and even better on linux-ampere (more hits of successful reservations)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the worst case it does 8 probes (decreasing 1Gb by 128Mb each iteration and increasing startAddress by 8mb) and bails out

#endif
const int32_t MinAllocSize = 128 * 1024 * 1024;

// Try to find and reserve an available region of virtual memory that is located
// within 2GB range (defined by the MaxExecutableMemorySizeNearCoreClr constant) from the
Expand All @@ -2161,12 +2172,18 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory()
{
// Try to allocate above the location of libcoreclr
preferredStartAddress = coreclrLoadAddress + CoreClrLibrarySize;
preferredStartAddressIncrement = MemoryProbingIncrement;
preferredStartAddressIncrement = AddressProbingIncrement;
}
else
{
// Try to allocate below the location of libcoreclr
preferredStartAddress = coreclrLoadAddress - MaxExecutableMemorySizeNearCoreClr;
#ifndef TARGET_XARCH
// For arm for the "high addresss" case it only makes sense to try to reserve 128Mb
// and if it doesn't work - we'll reserve a full-sized region in a random location
sizeOfAllocation = MinAllocSize;
#endif

preferredStartAddress = coreclrLoadAddress - sizeOfAllocation;
preferredStartAddressIncrement = 0;
}

Expand All @@ -2180,10 +2197,10 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory()
}

// Try to allocate a smaller region
sizeOfAllocation -= MemoryProbingIncrement;
sizeOfAllocation -= AllocSizeProbingDecrement;
preferredStartAddress += preferredStartAddressIncrement;

} while (sizeOfAllocation >= MemoryProbingIncrement);
} while (sizeOfAllocation >= MinAllocSize);

if (m_startAddress == nullptr)
{
Expand Down