// Copyright Epic Games, Inc. All Rights Reserved. #include "zencore/system.h" #include #include #include #if ZEN_PLATFORM_WINDOWS # include ZEN_THIRD_PARTY_INCLUDES_START # include # include ZEN_THIRD_PARTY_INCLUDES_END #elif ZEN_PLATFORM_LINUX # include #elif ZEN_PLATFORM_MAC # include #endif namespace zen { using namespace std::literals; int g_FakeCpuCount = 0; void SetCpuCountForReporting(int FakeCpuCount) { g_FakeCpuCount = FakeCpuCount; } #if ZEN_PLATFORM_WINDOWS std::string GetMachineName() { WCHAR NameBuffer[256]; DWORD dwNameSize = 255; BOOL Success = GetComputerNameW(NameBuffer, &dwNameSize); if (Success) { return WideToUtf8(NameBuffer); } return {}; } SystemMetrics GetSystemMetrics() { SYSTEM_INFO SysInfo{}; GetSystemInfo(&SysInfo); SystemMetrics Metrics; Metrics.LogicalProcessorCount = SysInfo.dwNumberOfProcessors; // Determine physical core count DWORD BufferSize = 0; BOOL Result = GetLogicalProcessorInformation(nullptr, &BufferSize); if (int32_t Error = GetLastError(); Error != ERROR_INSUFFICIENT_BUFFER) { ThrowSystemError(Error, "Failed to get buffer size for logical processor information"); } PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)Memory::Alloc(BufferSize); Result = GetLogicalProcessorInformation(Buffer, &BufferSize); if (!Result) { Memory::Free(Buffer); throw std::runtime_error("Failed to get logical processor information"); } DWORD ProcessorPkgCount = 0; DWORD ProcessorCoreCount = 0; DWORD ByteOffset = 0; while (ByteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= BufferSize) { const SYSTEM_LOGICAL_PROCESSOR_INFORMATION& Slpi = Buffer[ByteOffset / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)]; if (Slpi.Relationship == RelationProcessorCore) { ProcessorCoreCount++; } else if (Slpi.Relationship == RelationProcessorPackage) { ProcessorPkgCount++; } ByteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); } Metrics.CoreCount = ProcessorCoreCount; Metrics.CpuCount = ProcessorPkgCount; Memory::Free(Buffer); // Query memory status MEMORYSTATUSEX MemStatus{.dwLength = sizeof(MEMORYSTATUSEX)}; GlobalMemoryStatusEx(&MemStatus); Metrics.SystemMemoryMiB = MemStatus.ullTotalPhys / 1024 / 1024; Metrics.AvailSystemMemoryMiB = MemStatus.ullAvailPhys / 1024 / 1024; Metrics.VirtualMemoryMiB = MemStatus.ullTotalVirtual / 1024 / 1024; Metrics.AvailVirtualMemoryMiB = MemStatus.ullAvailVirtual / 1024 / 1024; Metrics.PageFileMiB = MemStatus.ullTotalPageFile / 1024 / 1024; Metrics.AvailPageFileMiB = MemStatus.ullAvailPageFile / 1024 / 1024; return Metrics; } #elif ZEN_PLATFORM_LINUX std::string GetMachineName() { static char Result[256] = ""; if (!Result[0]) { struct utsname name; const char* SysName = name.nodename; if (uname(&name)) { SysName = "Unix Computer"; } strcpy(Result, SysName); } return Result; } SystemMetrics GetSystemMetrics() { return {}; } #elif ZEN_PLATFORM_MAC std::string GetMachineName() { static char Result[256] = ""; if (!Result[0]) { gethostname(Result, sizeof(Result)); } return Result; } SystemMetrics GetSystemMetrics() { return {}; } #else # error "Unknown platform" #endif SystemMetrics GetSystemMetricsForReporting() { SystemMetrics Sm = GetSystemMetrics(); if (g_FakeCpuCount) { Sm.CoreCount = g_FakeCpuCount; Sm.LogicalProcessorCount = g_FakeCpuCount; } return Sm; } std::string_view GetOperatingSystemName() { return ZEN_PLATFORM_NAME; } std::string_view GetCpuName() { #if ZEN_ARCH_X64 return "x64"sv; #elif ZEN_ARCH_ARM64 return "arm64"sv; #endif } void Describe(const SystemMetrics& Metrics, CbWriter& Writer) { Writer << "cpu_count" << Metrics.CpuCount << "core_count" << Metrics.CoreCount << "lp_count" << Metrics.LogicalProcessorCount << "total_memory_mb" << Metrics.SystemMemoryMiB << "avail_memory_mb" << Metrics.AvailSystemMemoryMiB << "total_virtual_mb" << Metrics.VirtualMemoryMiB << "avail_virtual_mb" << Metrics.AvailVirtualMemoryMiB << "total_pagefile_mb" << Metrics.PageFileMiB << "avail_pagefile_mb" << Metrics.AvailPageFileMiB; } } // namespace zen