Кроссплатформенный способ узнать примерное количество RAM памяти

Собственно, пока в голову пришел немного топорный метод:

     BYTE GetAvailableMemory(){

        llu MaxMemory = Settings::defaultmemory; // Gb
        std::vector<BYTE> tester;

        while (true){
            try {
                tester.resize(MaxMemory*1073741824);
            } catch (std::bad_alloc& e) {
                tester.clear();
                MaxMemory--;
                return ((MaxMemory) >= Settings::defaultmemory) ? MaxMemory : 0;
            }
            MaxMemory++;
        }
        return 0;
    }

Данный метод работает на системе с 16 GB оперативки,
НО! Первое - он не работает (хз почему) на 32 битных системах, т.к. уже на выделении 2Gb вектора улетает в ошибку Второе - этот метод выполняется около 12 секунд, что тоже долго.
Собственно мой вопрос - можно ли как-то оптимизировать этот топорный подсчитыватель памяти и будет ли он также работать на линукс и маке, как на винде (не положит ли он систему)?


Ответы (2 шт):

Автор решения: AndryS1

Для windows корректнее будет следующий способ

#include <Windows.h> 
typedef unsigned long long uint64_t;

uint64_t GetAvailableMemory() {
    typedef BOOL(WINAPI* PGMSE)(LPMEMORYSTATUSEX);

    PGMSE pGMSE = (PGMSE)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx");
    if (pGMSE != 0)
    {
        MEMORYSTATUSEX mi;
        memset(&mi, 0, sizeof(MEMORYSTATUSEX));
        mi.dwLength = sizeof(MEMORYSTATUSEX);
        if (pGMSE(&mi) == TRUE)
            return mi.ullAvailPhys;
        else
            pGMSE = 0;
    }
    if (pGMSE == 0)
    {
        MEMORYSTATUS mi;
        memset(&mi, 0, sizeof(MEMORYSTATUS));
        mi.dwLength = sizeof(MEMORYSTATUS);
        GlobalMemoryStatus(&mi);
        return mi.dwAvailPhys;
    }
    return 0; // или киньте исключение
}

Для Linux нужно будет смотреть в сторону /proc/meminfo Вот пример чтения MemFree

#include <fstream>

unsigned long get_mem_total() {
    std::string token;
    std::ifstream file("/proc/meminfo");
    while (file >> token) {
        if (token == "MemAvailable:") {
            unsigned long mem;
            if (file >> mem) {
                return mem;
            }
            else {
                return 0;
            }
        }
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return 0; // можете кинуть исключение
}

В любом случае делать это придётся препроцессорами

→ Ссылка
Автор решения: Maxim Timakov

Вариант для Linux: использовать функцию sysinfo

// get_info.cxx
#include <sys/sysinfo.h>

#include <iostream>

int main(int argc, const char** argv) {
    struct sysinfo info{};

    if (0 == sysinfo(&info))
    {
        std::cout << "info.freeram  : " << info.freeram << std::endl;
        std::cout << "info.totalram : " << info.totalram << std::endl;
    }
    else
    {
        std::cerr << "call sysinfo fail" << std::endl;
    }
    

    return 0;
}

сборка:

g++ get_info.cxx -o get_info

вывод на моей системе(Debian/testing)

$> free
              total        used        free      shared  buff/cache   available
Mem:       16399300     7191280      428588      166348     8779432     8751060
Swap:       8375292        4352     8370940

$> ./build/get_info
info.freeram  : 431308800
info.totalram : 16792883200
→ Ссылка