LCOV - code coverage report
Current view: top level - src/utils - MemoryUtils.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 35 42 83.3 %
Date: 2025-07-17 01:28:37 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "MemoryUtils.h"
      11             : #include "MooseError.h"
      12             : 
      13             : #include <unistd.h>
      14             : #include <mpi.h>
      15             : #include <fstream>
      16             : #include <array>
      17             : 
      18             : #if defined(__APPLE__)
      19             : #include <mach/task.h>
      20             : #include <mach/clock.h>
      21             : #include <mach/mach.h>
      22             : #include <mach/vm_page_size.h>
      23             : #include <sys/types.h>
      24             : #include <sys/sysctl.h>
      25             : #include <sys/vmmeter.h>
      26             : #elif defined(__WIN32__)
      27             : #include <windows.h>
      28             : #include <psapi.h>
      29             : #include <processthreadsapi.h>
      30             : #include <sysinfoapi.h>
      31             : #else
      32             : #include <sys/sysinfo.h>
      33             : #endif
      34             : 
      35             : namespace MemoryUtils
      36             : {
      37             : 
      38             : std::string
      39           0 : getMPIProcessorName()
      40             : {
      41             : #ifdef LIBMESH_HAVE_MPI
      42             :   int mpi_namelen;
      43             :   char mpi_name[MPI_MAX_PROCESSOR_NAME];
      44           0 :   MPI_Get_processor_name(mpi_name, &mpi_namelen);
      45           0 :   return mpi_name;
      46             : #else
      47             :   return "serial";
      48             : #endif
      49             : }
      50             : 
      51             : MooseEnum
      52       29626 : getMemUnitsEnum()
      53             : {
      54             :   return MooseEnum("bytes kibibytes mebibytes gibibytes kilobytes megabytes gigabytes",
      55       29626 :                    "mebibytes");
      56             : }
      57             : 
      58             : std::size_t
      59         548 : getTotalRAM()
      60             : {
      61             : #if defined(__APPLE__)
      62             :   uint64_t hwmem_size;
      63             :   size_t length = sizeof(hwmem_size);
      64             :   if (0 <= sysctlbyname("hw.memsize", &hwmem_size, &length, NULL, 0))
      65             :     return hwmem_size;
      66             : #elif defined(__WIN32__)
      67             :   ULONGLONG mem_kb;
      68             :   if (GetPhysicallyInstalledSystemMemory(&mem_kb))
      69             :     return mem_kb * 1024;
      70             : #else
      71             :   struct sysinfo si_data;
      72         548 :   if (!sysinfo(&si_data))
      73         548 :     return si_data.totalram * si_data.mem_unit;
      74             : #endif
      75           0 :   return 0;
      76             : }
      77             : 
      78             : bool
      79   186659728 : getMemoryStats(Stats & stats)
      80             : {
      81   186659728 :   bool retval = false;
      82             : 
      83             :   enum StatItem
      84             :   {
      85             :     index_page_faults = 8,
      86             :     index_virtual_size = 19,
      87             :     index_resident_size = 20,
      88             :     num = 21 // total number of entries read
      89             :   };
      90             : 
      91             :   // inspect /proc
      92   186659728 :   std::ifstream stat_stream("/proc/self/stat", std::ios_base::in);
      93             :   std::array<std::size_t, 21> val;
      94   186659728 :   val.fill(0);
      95             : 
      96   186659728 :   if (stat_stream)
      97             :   {
      98             :     // if the proc filesystem file is found (Linux) read its contents
      99   186659728 :     std::string pid, comm, state;
     100   186659728 :     stat_stream >> pid >> comm >> state;
     101             : 
     102   186659728 :     unsigned int i = 0;
     103             : 
     104  4106514016 :     while (!stat_stream.eof() && i < val.size())
     105             :     {
     106  3919854288 :       stat_stream >> val[i];
     107  3919854288 :       i++;
     108             :     }
     109             : 
     110             :     // Handle the case where we didn't get enough values by just zeroing everything
     111             :     // since we probably got junk
     112   186659728 :     if (i != val.size())
     113           0 :       val.fill(0);
     114             :     else
     115   186659728 :       retval = true;
     116             : 
     117             :       // resident size is reported as number of pages in /proc
     118             : #ifndef __WIN32__
     119   186659728 :     val[index_resident_size] *= sysconf(_SC_PAGE_SIZE);
     120             : #endif
     121   186659728 :   }
     122             :   else
     123             :   {
     124             : #ifdef __WIN32__
     125             :     auto pid = GetCurrentProcessId();
     126             :     auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
     127             : 
     128             :     PROCESS_MEMORY_COUNTERS pmc;
     129             :     if (NULL == hProcess || !GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
     130             :       val.fill(0);
     131             :     else
     132             :     {
     133             :       retval = true;
     134             :       val[index_page_faults] = pmc.PageFaultCount;
     135             :       val[index_virtual_size] = pmc.WorkingSetSize + pmc.PagefileUsage;
     136             :       val[index_resident_size] = pmc.WorkingSetSize;
     137             :     }
     138             : #else
     139             :     // set all data entries to zero (if all else should fail)
     140           0 :     val.fill(0);
     141             : #endif
     142             : 
     143             : // obtain mach task info on mac OS
     144             : #if defined(__APPLE__)
     145             :     struct task_basic_info t_info;
     146             :     mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
     147             :     if (KERN_SUCCESS == task_info(mach_task_self(),
     148             :                                   TASK_BASIC_INFO,
     149             :                                   reinterpret_cast<task_info_t>(&t_info),
     150             :                                   &t_info_count))
     151             :     {
     152             :       retval = true;
     153             :       val[index_virtual_size] = t_info.virtual_size;   // in bytes
     154             :       val[index_resident_size] = t_info.resident_size; // in bytes
     155             :     }
     156             :     else
     157             :       mooseDoOnce(::mooseWarning("task_info call failed, memory usage numbers will be incorrect"));
     158             : #endif
     159             :   }
     160             : 
     161             :   // physical mem
     162   186659728 :   stats._physical_memory = val[index_resident_size];
     163             : 
     164             :   // virtual mem
     165   186659728 :   stats._virtual_memory = val[index_virtual_size];
     166             : 
     167             :   // page faults
     168   186659728 :   stats._page_faults = val[index_page_faults];
     169             : 
     170   186659728 :   return retval;
     171   186659728 : }
     172             : 
     173             : std::size_t
     174   186660043 : convertBytes(std::size_t bytes, MemUnits unit)
     175             : {
     176   186660043 :   if (unit == MemUnits::Bytes)
     177         840 :     return bytes;
     178             : 
     179   186659203 :   unsigned int nunit = static_cast<unsigned int>(unit);
     180             : 
     181             :   // kibi, mebi, gibi
     182   186659203 :   if (nunit <= 3)
     183         705 :     return bytes >> (nunit * 10);
     184             : 
     185             :   // kilo, mega, giga
     186   186658498 :   if (nunit <= 6)
     187             :   {
     188   559975380 :     while (nunit-- > 3)
     189   373316882 :       bytes /= 1000;
     190   186658498 :     return bytes;
     191             :   }
     192             : 
     193           0 :   mooseError("Unknown memory unit");
     194             : }
     195             : 
     196             : } // namespace MemoryUtils

Generated by: LCOV version 1.14