fix(EnsureAvailableMemory/macOS): warn based on memory pressure rather than available RAM

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
This commit is contained in:
Octol1ttle 2026-04-14 18:44:53 +05:00
parent ae331cfc9a
commit 0b578fa767
No known key found for this signature in database
GPG key ID: B77C34313AEE1FFF
4 changed files with 83 additions and 10 deletions

View file

@ -141,7 +141,6 @@ uint64_t HardwareInfo::availableRamMiB()
} }
#elif defined(Q_OS_MACOS) #elif defined(Q_OS_MACOS)
#include "mach/mach.h"
#include "sys/sysctl.h" #include "sys/sysctl.h"
QString HardwareInfo::cpuInfo() QString HardwareInfo::cpuInfo()
@ -171,18 +170,32 @@ uint64_t HardwareInfo::totalRamMiB()
uint64_t HardwareInfo::availableRamMiB() uint64_t HardwareInfo::availableRamMiB()
{ {
mach_port_t host_port = mach_host_self(); return 0;
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; }
vm_statistics64_data_t vm_stats; MacOSHardwareInfo::MemoryPressureLevel MacOSHardwareInfo::memoryPressureLevel()
{
if (host_statistics64(host_port, HOST_VM_INFO64, reinterpret_cast<host_info64_t>(&vm_stats), &count) == KERN_SUCCESS) { uint32_t level;
// transforming bytes -> mib size_t levelSize = sizeof level;
return (vm_stats.free_count + vm_stats.inactive_count) * vm_page_size / 1024 / 1024; if (sysctlbyname("kern.memorystatus_vm_pressure_level", &level, &levelSize, nullptr, 0) == 0) {
return static_cast<MemoryPressureLevel>(level);
} }
qWarning() << "Could not get available RAM: host_statistics64"; qWarning() << "Could not get memory pressure level: sysctlbyname";
return 0; return MemoryPressureLevel::Normal;
}
QString MacOSHardwareInfo::memoryPressureLevelName()
{
// The names are internal, users refer to levels by their graph colors in Activity Monitor
switch (memoryPressureLevel()) {
case MemoryPressureLevel::Normal:
return "Green";
case MemoryPressureLevel::Warning:
return "Yellow";
case MemoryPressureLevel::Critical:
return "Red";
}
} }
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)

View file

@ -27,3 +27,16 @@ uint64_t totalRamMiB();
uint64_t availableRamMiB(); uint64_t availableRamMiB();
QStringList gpuInfo(); QStringList gpuInfo();
} // namespace HardwareInfo } // namespace HardwareInfo
#ifdef Q_OS_MACOS
namespace MacOSHardwareInfo {
enum class MemoryPressureLevel : uint8_t {
Normal = 1,
Warning = 2,
Critical = 4,
};
MemoryPressureLevel memoryPressureLevel();
QString memoryPressureLevelName();
} // namespace MacOSHardwareInfo
#endif

View file

@ -25,6 +25,47 @@ EnsureAvailableMemory::EnsureAvailableMemory(LaunchTask* parent, MinecraftInstan
void EnsureAvailableMemory::executeTask() void EnsureAvailableMemory::executeTask()
{ {
#ifdef Q_OS_MACOS
QString text;
switch (MacOSHardwareInfo::memoryPressureLevel()) {
case MacOSHardwareInfo::MemoryPressureLevel::Normal:
emitSucceeded();
return;
case MacOSHardwareInfo::MemoryPressureLevel::Warning:
text =
tr("The system is under increased memory pressure. This may cause lag or slowdowns.\n"
"If possible, close other applications before continuing.\n\n"
"Launch anyway?");
break;
case MacOSHardwareInfo::MemoryPressureLevel::Critical:
text =
tr("Your system is under critical memory pressure. This may lead to severe slowdowns or crashes.\n"
"It is highly recommended to close other applications or restart your system.\n\n"
"Launch anyway?");
break;
}
bool shouldAbort = false;
if (m_instance->settings()->get("LowMemWarning").toBool()) {
auto* dialog = CustomMessageBox::selectable(nullptr, tr("High memory pressure"), text, QMessageBox::Icon::Warning,
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No,
QMessageBox::StandardButton::No);
shouldAbort = dialog->exec() == QMessageBox::No;
dialog->deleteLater();
}
const auto message = tr("The system is under high memory pressure");
if (shouldAbort) {
emit logLine(message, MessageLevel::Fatal);
emitFailed(message);
return;
}
emit logLine(message, MessageLevel::Warning);
emitSucceeded();
#else
const uint64_t available = HardwareInfo::availableRamMiB(); const uint64_t available = HardwareInfo::availableRamMiB();
if (available == 0) { if (available == 0) {
// could not read // could not read
@ -66,4 +107,5 @@ void EnsureAvailableMemory::executeTask()
} }
emitSucceeded(); emitSucceeded();
#endif
} }

View file

@ -68,7 +68,12 @@ void PrintInstanceInfo::executeTask()
::runPciconf(log); ::runPciconf(log);
#else #else
log << "CPU: " + HardwareInfo::cpuInfo(); log << "CPU: " + HardwareInfo::cpuInfo();
#ifdef Q_OS_MACOS
log << "Memory pressure level: " + MacOSHardwareInfo::memoryPressureLevelName();
#else
log << QString("RAM: %1 MiB (available: %2 MiB)").arg(HardwareInfo::totalRamMiB()).arg(HardwareInfo::availableRamMiB()); log << QString("RAM: %1 MiB (available: %2 MiB)").arg(HardwareInfo::totalRamMiB()).arg(HardwareInfo::availableRamMiB());
#endif
#endif #endif
log.append(HardwareInfo::gpuInfo()); log.append(HardwareInfo::gpuInfo());
log << ""; log << "";