Skip to content

Commit 449d29c

Browse files
committed
Fix computing available memory on OSX for GC
We were using the `vm_statistics_data_t::free_count` as the available memory reported to the GC. It turned out this value is only a small portion of the available memory and that the appropriate value should be based on the kern.memorystatus_level value obtained using sysctl. That value represents percentual amount of available memory, so multiplying it by the total memory bytes gets the available memory bytes. Close #94846
1 parent f2c3541 commit 449d29c

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

src/coreclr/gc/unix/gcenv.unix.cpp

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,17 @@ AffinitySet g_processAffinitySet;
220220
extern "C" int g_highestNumaNode;
221221
extern "C" bool g_numaAvailable;
222222

223+
#ifdef TARGET_APPLE
224+
static int *g_kern_memorystatus_level_mib = NULL;
225+
static size_t g_kern_memorystatus_level_mib_length = 0;
226+
#endif
227+
223228
// Initialize the interface implementation
224229
// Return:
225230
// true if it has succeeded, false if it has failed
226231
bool GCToOSInterface::Initialize()
227232
{
233+
bool success = true;
228234
int pageSize = sysconf( _SC_PAGE_SIZE );
229235

230236
g_pageSizeUnixInl = uint32_t((pageSize > 0) ? pageSize : 0x1000);
@@ -317,7 +323,24 @@ bool GCToOSInterface::Initialize()
317323

318324
NUMASupportInitialize();
319325

320-
return true;
326+
#ifdef TARGET_APPLE
327+
const char* mem_free_name = "kern.memorystatus_level";
328+
int rc = sysctlnametomib(mem_free_name, NULL, &g_kern_memorystatus_level_mib_length);
329+
if (rc == 0)
330+
{
331+
g_kern_memorystatus_level_mib = (int*)malloc(g_kern_memorystatus_level_mib_length * sizeof(int));
332+
rc = sysctlnametomib(mem_free_name, g_kern_memorystatus_level_mib, &g_kern_memorystatus_level_mib_length);
333+
if (rc != 0)
334+
{
335+
free(g_kern_memorystatus_level_mib);
336+
g_kern_memorystatus_level_mib = NULL;
337+
g_kern_memorystatus_level_mib_length = 0;
338+
success = false;
339+
}
340+
}
341+
#endif
342+
343+
return success;
321344
}
322345

323346
// Shutdown the interface implementation
@@ -1248,20 +1271,23 @@ uint64_t GetAvailablePhysicalMemory()
12481271

12491272
// Get the physical memory available.
12501273
#if defined(__APPLE__)
1251-
vm_size_t page_size;
1252-
mach_port_t mach_port;
1253-
mach_msg_type_number_t count;
1254-
vm_statistics_data_t vm_stats;
1255-
mach_port = mach_host_self();
1256-
count = sizeof(vm_stats) / sizeof(natural_t);
1257-
if (KERN_SUCCESS == host_page_size(mach_port, &page_size))
1274+
uint32_t mem_free = 0;
1275+
size_t mem_free_length = sizeof(uint32_t);
1276+
if (g_kern_memorystatus_level_mib != NULL)
12581277
{
1259-
if (KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count))
1278+
int rc = sysctl(g_kern_memorystatus_level_mib, g_kern_memorystatus_level_mib_length, &mem_free, &mem_free_length, NULL, 0);
1279+
if (rc == 0)
12601280
{
1261-
available = (int64_t)vm_stats.free_count * (int64_t)page_size;
1281+
int64_t mem_size = 0;
1282+
size_t mem_size_length = sizeof(int64_t);
1283+
int mib[] = { CTL_HW, HW_MEMSIZE };
1284+
rc = sysctl(mib, 2, &mem_size, &mem_size_length, NULL, 0);
1285+
if (rc == 0)
1286+
{
1287+
available = (int64_t)mem_free * mem_size / 100;
1288+
}
12621289
}
12631290
}
1264-
mach_port_deallocate(mach_task_self(), mach_port);
12651291
#elif defined(__FreeBSD__)
12661292
size_t inactive_count = 0, laundry_count = 0, free_count = 0;
12671293
size_t sz = sizeof(inactive_count);
@@ -1279,7 +1305,7 @@ uint64_t GetAvailablePhysicalMemory()
12791305

12801306
if (tryReadMemInfo)
12811307
{
1282-
// Ensure that we don't try to read the /proc/meminfo in successive calls to the GlobalMemoryStatusEx
1308+
// Ensure that we don't try to read the /proc/meminfo in successive calls to the GetAvailablePhysicalMemory
12831309
// if we have failed to access the file or the file didn't contain the MemAvailable value.
12841310
tryReadMemInfo = ReadMemAvailable(&available);
12851311
}

0 commit comments

Comments
 (0)