1 /* Authors: Lutong Wang and Bangqi Xu */
2 /*
3 * Copyright (c) 2019, The Regents of the University of California
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the University nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Author: David Robert Nadeau
31 * Site: http://NadeauSoftware.com/
32 * License: Creative Commons Attribution 3.0 Unported License
33 * http://creativecommons.org/licenses/by/3.0/deed.en_US
34 */
35
36 #if defined(_WIN32)
37 #include <psapi.h>
38 #include <windows.h>
39
40 #elif defined(__unix__) || defined(__unix) || defined(unix) \
41 || (defined(__APPLE__) && defined(__MACH__))
42 #include <sys/resource.h>
43 #include <unistd.h>
44
45 #if defined(__APPLE__) && defined(__MACH__)
46 #include <mach/mach.h>
47
48 #elif (defined(_AIX) || defined(__TOS__AIX__)) \
49 || (defined(__sun__) || defined(__sun) \
50 || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
51 #include <fcntl.h>
52 #include <procfs.h>
53
54 #elif defined(__linux__) || defined(__linux) || defined(linux) \
55 || defined(__gnu_linux__)
56 #include <stdio.h>
57
58 #endif
59
60 #else
61 #error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
62 #endif
63
64 /**
65 * Returns the peak (maximum so far) resident set size (physical
66 * memory use) measured in bytes, or zero if the value cannot be
67 * determined on this OS.
68 */
getPeakRSS()69 size_t getPeakRSS()
70 {
71 #if defined(_WIN32)
72 /* Windows -------------------------------------------------- */
73 PROCESS_MEMORY_COUNTERS info;
74 GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
75 return (size_t) info.PeakWorkingSetSize;
76
77 #elif (defined(_AIX) || defined(__TOS__AIX__)) \
78 || (defined(__sun__) || defined(__sun) \
79 || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
80 /* AIX and Solaris ------------------------------------------ */
81 struct psinfo psinfo;
82 int fd = -1;
83 if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
84 return (size_t) 0L; /* Can't open? */
85 if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
86 close(fd);
87 return (size_t) 0L; /* Can't read? */
88 }
89 close(fd);
90 return (size_t)(psinfo.pr_rssize * 1024L);
91
92 #elif defined(__unix__) || defined(__unix) || defined(unix) \
93 || (defined(__APPLE__) && defined(__MACH__))
94 /* BSD, Linux, and OSX -------------------------------------- */
95 struct rusage rusage;
96 getrusage(RUSAGE_SELF, &rusage);
97 #if defined(__APPLE__) && defined(__MACH__)
98 return (size_t) rusage.ru_maxrss;
99 #else
100 return (size_t)(rusage.ru_maxrss * 1024L);
101 #endif
102
103 #else
104 /* Unknown OS ----------------------------------------------- */
105 return (size_t) 0L; /* Unsupported. */
106 #endif
107 }
108
109 /**
110 * Returns the current resident set size (physical memory use) measured
111 * in bytes, or zero if the value cannot be determined on this OS.
112 */
getCurrentRSS()113 size_t getCurrentRSS()
114 {
115 #if defined(_WIN32)
116 /* Windows -------------------------------------------------- */
117 PROCESS_MEMORY_COUNTERS info;
118 GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
119 return (size_t) info.WorkingSetSize;
120
121 #elif defined(__APPLE__) && defined(__MACH__)
122 /* OSX ------------------------------------------------------ */
123 struct mach_task_basic_info info;
124 mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
125 if (task_info(mach_task_self(),
126 MACH_TASK_BASIC_INFO,
127 (task_info_t) &info,
128 &infoCount)
129 != KERN_SUCCESS)
130 return (size_t) 0L; /* Can't access? */
131 return (size_t) info.resident_size;
132
133 #elif defined(__linux__) || defined(__linux) || defined(linux) \
134 || defined(__gnu_linux__)
135 /* Linux ---------------------------------------------------- */
136 long rss = 0L;
137 FILE* fp = NULL;
138 if ((fp = fopen("/proc/self/statm", "r")) == NULL)
139 return (size_t) 0L; /* Can't open? */
140 if (fscanf(fp, "%*s%ld", &rss) != 1) {
141 fclose(fp);
142 return (size_t) 0L; /* Can't read? */
143 }
144 fclose(fp);
145 return (size_t) rss * (size_t) sysconf(_SC_PAGESIZE);
146
147 #else
148 /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
149 return (size_t) 0L; /* Unsupported. */
150 #endif
151 }
152