Browse Source
Complete redesign of memory monitoring in resource.c.
Complete redesign of memory monitoring in resource.c.
Acquiring memory size is done by four functions getMemorySize, getAvailableMemorySize, getPeakRSS, and getCurrentRSS. Time data are still obtained without code modifications.pre-master-46
7 changed files with 421 additions and 112 deletions
-
3src/frontend/Makefile.am
-
140src/frontend/get_avail_mem_size.c
-
119src/frontend/get_phys_mem_size.c
-
125src/frontend/get_resident_set_size.c
-
138src/frontend/resource.c
-
5src/frontend/resource.h
-
3visualc/vngspice.vcxproj
@ -0,0 +1,140 @@ |
|||||
|
/* |
||||
|
* Author: Holger Vogt |
||||
|
* License: 3-clause BSD License |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
|
||||
|
#if defined(_WIN32) |
||||
|
#undef BOOLEAN |
||||
|
#include <Windows.h> |
||||
|
|
||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) |
||||
|
#include <unistd.h> |
||||
|
#include <sys/types.h> |
||||
|
#include <sys/param.h> |
||||
|
#if defined(BSD) |
||||
|
#include <sys/sysctl.h> |
||||
|
#endif |
||||
|
#if defined(__APPLE__) && defined(__MACH__) |
||||
|
#import <mach/mach.h> |
||||
|
#import <mach/mach_host.h> |
||||
|
#endif |
||||
|
#else |
||||
|
#error "Unable to define getMemorySize( ) for an unknown OS." |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Returns the size of available memory (RAM) in bytes. |
||||
|
*/ |
||||
|
unsigned long long getAvailableMemorySize( ) |
||||
|
{ |
||||
|
#if defined(HAVE__PROC_MEMINFO) |
||||
|
/* Cygwin , Linux--------------------------------- */ |
||||
|
/* Search for string "MemFree" */ |
||||
|
FILE *fp; |
||||
|
char buffer[2048]; |
||||
|
size_t bytes_read; |
||||
|
char *match; |
||||
|
unsigned long long mem_got; |
||||
|
|
||||
|
if ((fp = fopen("/proc/meminfo", "r")) == NULL) { |
||||
|
perror("fopen(\"/proc/meminfo\")"); |
||||
|
return 0L; |
||||
|
} |
||||
|
|
||||
|
bytes_read = fread(buffer, 1, sizeof(buffer), fp); |
||||
|
fclose(fp); |
||||
|
if (bytes_read == 0 || bytes_read == sizeof(buffer)) |
||||
|
return 0L; |
||||
|
buffer[bytes_read] = '\0'; |
||||
|
match = strstr(buffer, "MemFree"); |
||||
|
if (match == NULL) /* not found */ |
||||
|
return 0L; |
||||
|
sscanf(match, "MemFree: %llu", &mem_got); |
||||
|
return mem_got * 1024; |
||||
|
|
||||
|
#elif defined(_WIN32) |
||||
|
/* Windows. ------------------------------------------------- */ |
||||
|
MEMORYSTATUSEX status; |
||||
|
status.dwLength = sizeof(status); |
||||
|
GlobalMemoryStatusEx( &status ); |
||||
|
return (size_t)status.ullAvailPhys; |
||||
|
|
||||
|
#elif defined(__APPLE__) && defined(__MACH__) |
||||
|
|
||||
|
mach_port_t host_port; |
||||
|
mach_msg_type_number_t host_size; |
||||
|
vm_size_t pagesize; |
||||
|
|
||||
|
host_port = mach_host_self(); |
||||
|
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
||||
|
host_page_size(host_port, &pagesize); |
||||
|
|
||||
|
vm_statistics_data_t vm_stat; |
||||
|
|
||||
|
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t) &vm_stat, |
||||
|
&host_size) != KERN_SUCCESS) { |
||||
|
NSLog(@"Failed to fetch vm statistics"); |
||||
|
} |
||||
|
|
||||
|
/* Stats in bytes */ |
||||
|
/* natural_t mem_used = (vm_stat.active_count + vm_stat.inactive_count + |
||||
|
vm_stat.wire_count) * pagesize; */ |
||||
|
return vm_stat.free_count * pagesize; |
||||
|
// natural_t mem_total = mem_used + mem_free; |
||||
|
|
||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) |
||||
|
/* Linux/UNIX variants. ------------------------------------------- */ |
||||
|
/* Prefer sysctl() over sysconf() except sysctl() HW_REALMEM and HW_PHYSMEM */ |
||||
|
|
||||
|
#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64)) |
||||
|
int mib[2]; |
||||
|
mib[0] = CTL_HW; |
||||
|
#if defined(HW_MEMSIZE) |
||||
|
mib[1] = HW_MEMSIZE; /* OSX. --------------------- */ |
||||
|
#elif defined(HW_PHYSMEM64) |
||||
|
mib[1] = HW_PHYSMEM64; /* NetBSD, OpenBSD. --------- */ |
||||
|
#endif |
||||
|
int64_t size = 0; /* 64-bit */ |
||||
|
size_t len = sizeof( size ); |
||||
|
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) |
||||
|
return (size_t)size; |
||||
|
return 0L; /* Failed? */ |
||||
|
|
||||
|
#elif defined(_SC_AIX_REALMEM) |
||||
|
/* AIX. ----------------------------------------------------- */ |
||||
|
return (size_t)sysconf( _SC_AIX_REALMEM ) * (size_t)1024L; |
||||
|
|
||||
|
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) |
||||
|
/* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */ |
||||
|
return (size_t)sysconf( _SC_PHYS_PAGES ) * |
||||
|
(size_t)sysconf( _SC_PAGESIZE ); |
||||
|
|
||||
|
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE) |
||||
|
/* Legacy. -------------------------------------------------- */ |
||||
|
return (size_t)sysconf( _SC_PHYS_PAGES ) * |
||||
|
(size_t)sysconf( _SC_PAGE_SIZE ); |
||||
|
|
||||
|
#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM)) |
||||
|
/* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */ |
||||
|
int mib[2]; |
||||
|
mib[0] = CTL_HW; |
||||
|
#if defined(HW_REALMEM) |
||||
|
mib[1] = HW_REALMEM; /* FreeBSD. ----------------- */ |
||||
|
#elif defined(HW_PYSMEM) |
||||
|
mib[1] = HW_PHYSMEM; /* Others. ------------------ */ |
||||
|
#endif |
||||
|
unsigned int size = 0; /* 32-bit */ |
||||
|
size_t len = sizeof( size ); |
||||
|
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) |
||||
|
return (size_t)size; |
||||
|
return 0L; /* Failed? */ |
||||
|
#endif /* sysctl and sysconf variants */ |
||||
|
|
||||
|
#else |
||||
|
return 0L; /* Unknown OS. */ |
||||
|
#endif |
||||
|
} |
||||
@ -0,0 +1,119 @@ |
|||||
|
/* |
||||
|
* Author: David Robert Nadeau |
||||
|
* Site: http://NadeauSoftware.com/ |
||||
|
* License: Creative Commons Attribution 3.0 Unported License |
||||
|
* http://creativecommons.org/licenses/by/3.0/deed.en_US |
||||
|
* Modified: Holger Vogt, 2019 |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
|
||||
|
#if defined(_WIN32) |
||||
|
#undef BOOLEAN |
||||
|
#include <Windows.h> |
||||
|
|
||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) |
||||
|
#include <unistd.h> |
||||
|
#include <sys/types.h> |
||||
|
#include <sys/param.h> |
||||
|
#if defined(BSD) |
||||
|
#include <sys/sysctl.h> |
||||
|
#endif |
||||
|
|
||||
|
#else |
||||
|
#error "Unable to define getMemorySize( ) for an unknown OS." |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Returns the size of physical memory (RAM) in bytes. |
||||
|
*/ |
||||
|
unsigned long long getMemorySize() |
||||
|
{ |
||||
|
#if defined(HAVE__PROC_MEMINFO) |
||||
|
/* Cygwin , Linux--------------------------------- */ |
||||
|
FILE *fp; |
||||
|
char buffer[2048]; |
||||
|
size_t bytes_read; |
||||
|
char *match; |
||||
|
unsigned long long mem_got; |
||||
|
|
||||
|
if ((fp = fopen("/proc/meminfo", "r")) == NULL) { |
||||
|
perror("fopen(\"/proc/meminfo\")"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
bytes_read = fread(buffer, 1, sizeof(buffer), fp); |
||||
|
fclose(fp); |
||||
|
if (bytes_read == 0 || bytes_read == sizeof(buffer)) |
||||
|
return 0; |
||||
|
buffer[bytes_read] = '\0'; |
||||
|
/* Search for string "MemTotal" */ |
||||
|
match = strstr(buffer, "MemTotal"); |
||||
|
if (match == NULL) /* not found */ |
||||
|
return 0; |
||||
|
sscanf(match, "MemTotal: %llu", &mem_got); |
||||
|
return mem_got * 1024L; |
||||
|
|
||||
|
#elif defined(_WIN32) |
||||
|
/* Windows. ------------------------------------------------- */ |
||||
|
/* Use new 64-bit MEMORYSTATUSEX, not old 32-bit MEMORYSTATUS */ |
||||
|
MEMORYSTATUSEX status; |
||||
|
status.dwLength = sizeof(status); |
||||
|
GlobalMemoryStatusEx( &status ); |
||||
|
return (unsigned long long) status.ullTotalPhys; |
||||
|
|
||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || \ |
||||
|
(defined(__APPLE__) && defined(__MACH__)) |
||||
|
/* UNIX variants. ------------------------------------------- */ |
||||
|
/* Prefer sysctl() over sysconf() except sysctl() HW_REALMEM and HW_PHYSMEM */ |
||||
|
|
||||
|
#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64)) |
||||
|
int mib[2]; |
||||
|
mib[0] = CTL_HW; |
||||
|
#if defined(HW_MEMSIZE) |
||||
|
mib[1] = HW_MEMSIZE; /* OSX. --------------------- */ |
||||
|
#elif defined(HW_PHYSMEM64) |
||||
|
mib[1] = HW_PHYSMEM64; /* NetBSD, OpenBSD. --------- */ |
||||
|
#endif |
||||
|
int64_t size = 0; /* 64-bit */ |
||||
|
size_t len = sizeof( size ); |
||||
|
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) |
||||
|
return (unsigned long long) size; |
||||
|
return 0L; /* Failed? */ |
||||
|
|
||||
|
#elif defined(_SC_AIX_REALMEM) |
||||
|
/* AIX. ----------------------------------------------------- */ |
||||
|
return (unsigned long long) sysconf(_SC_AIX_REALMEM) * (size_t) 1024L; |
||||
|
|
||||
|
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) |
||||
|
/* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */ |
||||
|
return (unsigned long long) sysconf(_SC_PHYS_PAGES) * |
||||
|
(unsigned long long) sysconf(_SC_PAGESIZE); |
||||
|
|
||||
|
#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE) |
||||
|
/* Legacy. -------------------------------------------------- */ |
||||
|
return (unsigned long long) sysconf(_SC_PHYS_PAGES) * |
||||
|
(unsigned long long) sysconf(_SC_PAGE_SIZE); |
||||
|
|
||||
|
#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM)) |
||||
|
/* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */ |
||||
|
int mib[2]; |
||||
|
mib[0] = CTL_HW; |
||||
|
#if defined(HW_REALMEM) |
||||
|
mib[1] = HW_REALMEM; /* FreeBSD. ----------------- */ |
||||
|
#elif defined(HW_PYSMEM) |
||||
|
mib[1] = HW_PHYSMEM; /* Others. ------------------ */ |
||||
|
#endif |
||||
|
unsigned long long size = 0; /* 32-bit */ |
||||
|
size_t len = sizeof( size ); |
||||
|
if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) |
||||
|
return (unsigned long long) size; |
||||
|
return 0L; /* Failed? */ |
||||
|
#endif /* sysctl and sysconf variants */ |
||||
|
|
||||
|
#else |
||||
|
return 0L; /* Unknown OS. */ |
||||
|
#endif |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
/* |
||||
|
* Author: David Robert Nadeau |
||||
|
* Site: http://NadeauSoftware.com/ |
||||
|
* License: Creative Commons Attribution 3.0 Unported License |
||||
|
* http://creativecommons.org/licenses/by/3.0/deed.en_US |
||||
|
* Modified: Holger Vogt, 2019 |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
|
||||
|
#if defined(_WIN32) |
||||
|
#undef BOOLEAN |
||||
|
#include <windows.h> |
||||
|
#include <psapi.h> |
||||
|
|
||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) |
||||
|
#include <unistd.h> |
||||
|
#include <sys/resource.h> |
||||
|
|
||||
|
#if defined(__APPLE__) && defined(__MACH__) |
||||
|
#include <mach/mach.h> |
||||
|
|
||||
|
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) |
||||
|
#include <fcntl.h> |
||||
|
#include <procfs.h> |
||||
|
|
||||
|
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) |
||||
|
#include <stdio.h> |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#else |
||||
|
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS." |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Returns the peak (maximum so far) resident set size (physical |
||||
|
* memory use) measured in bytes, or zero if the value cannot be |
||||
|
* determined on this OS. |
||||
|
*/ |
||||
|
unsigned long long getPeakRSS() |
||||
|
{ |
||||
|
#if defined(HAVE_GETRUSAGE) |
||||
|
/* BSD, Linux, and OSX -------------------------------------- |
||||
|
* not (yet) available with CYGWIN */ |
||||
|
struct rusage rusage; |
||||
|
getrusage(RUSAGE_SELF, &rusage); |
||||
|
#if defined(__APPLE__) && defined(__MACH__) |
||||
|
return (unsigned long long) rusage.ru_maxrss; |
||||
|
#else |
||||
|
return (unsigned long long) (rusage.ru_maxrss * 1024L); |
||||
|
#endif |
||||
|
|
||||
|
#elif defined(_WIN32) |
||||
|
/* Windows -------------------------------------------------- */ |
||||
|
PROCESS_MEMORY_COUNTERS info; |
||||
|
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); |
||||
|
return (unsigned long long) info.PeakWorkingSetSize; |
||||
|
|
||||
|
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) |
||||
|
/* AIX and Solaris ------------------------------------------ */ |
||||
|
struct psinfo psinfo; |
||||
|
int fd = -1; |
||||
|
if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 ) |
||||
|
return 0L; /* Can't open? */ |
||||
|
if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) ) |
||||
|
{ |
||||
|
close( fd ); |
||||
|
return 0L; /* Can't read? */ |
||||
|
} |
||||
|
close( fd ); |
||||
|
return (unsigned long long) (psinfo.pr_rssize * 1024L); |
||||
|
|
||||
|
#else |
||||
|
/* Unknown OS ----------------------------------------------- */ |
||||
|
return 0L; /* Unsupported. */ |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Returns the current resident set size (physical memory use) measured |
||||
|
* in bytes, or zero if the value cannot be determined on this OS. |
||||
|
*/ |
||||
|
unsigned long long getCurrentRSS( ) |
||||
|
{ |
||||
|
#if defined(_WIN32) |
||||
|
/* Windows -------------------------------------------------- */ |
||||
|
PROCESS_MEMORY_COUNTERS info; |
||||
|
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); |
||||
|
return (unsigned long long) info.WorkingSetSize; |
||||
|
|
||||
|
#elif defined(__APPLE__) && defined(__MACH__) |
||||
|
/* OSX ------------------------------------------------------ */ |
||||
|
struct mach_task_basic_info info; |
||||
|
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; |
||||
|
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, |
||||
|
(task_info_t)&info, &infoCount ) != KERN_SUCCESS ) |
||||
|
return 0L; /* Can't access? */ |
||||
|
return (unsigned long long) info.resident_size; |
||||
|
|
||||
|
//#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) |
||||
|
#elif defined(HAVE__PROC_MEMINFO) |
||||
|
/* Linux ---------------------------------------------------- */ |
||||
|
unsigned long long rss = 0L; |
||||
|
FILE* fp = NULL; |
||||
|
if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL ) |
||||
|
return (unsigned long long) 0L; /* Can't open? */ |
||||
|
if ( fscanf( fp, "%*s%llu", &rss ) != 1 ) |
||||
|
{ |
||||
|
fclose( fp ); |
||||
|
return 0L; /* Can't read? */ |
||||
|
} |
||||
|
fclose( fp ); |
||||
|
return rss * (unsigned long long) sysconf(_SC_PAGESIZE); |
||||
|
|
||||
|
#else |
||||
|
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */ |
||||
|
return (unsigned long long) 0L; /* Unsupported. */ |
||||
|
#endif |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue