xref: /petsc/src/sys/memory/mem.c (revision a663daf8c8aa4dbb23bdeec1481de438984dc3b7)
1 
2 #include <petscsys.h>           /*I "petscsys.h" I*/
3 #if defined(PETSC_HAVE_PWD_H)
4 #include <pwd.h>
5 #endif
6 #include <ctype.h>
7 #include <sys/stat.h>
8 #if defined(PETSC_HAVE_UNISTD_H)
9 #include <unistd.h>
10 #endif
11 #if defined(PETSC_HAVE_SYS_UTSNAME_H)
12 #include <sys/utsname.h>
13 #endif
14 #include <fcntl.h>
15 #include <time.h>
16 #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
17 #include <sys/systeminfo.h>
18 #endif
19 
20 /* task_info seems to be buggy plus pgcc doesn't like including this file
21 #if defined(PETSC_HAVE_TASK_INFO)
22 #include <mach/mach.h>
23 #endif
24 */
25 
26 #if defined(PETSC_HAVE_SYS_RESOURCE_H)
27 #include <sys/resource.h>
28 #endif
29 #if defined(PETSC_HAVE_SYS_PROCFS_H)
30 /* #include <sys/int_types.h> Required if using gcc on solaris 2.6 */
31 #include <sys/procfs.h>
32 #endif
33 #if defined(PETSC_HAVE_FCNTL_H)
34 #include <fcntl.h>
35 #endif
36 
37 #undef __FUNCT__
38 #define __FUNCT__ "PetscMemoryGetCurrentUsage"
39 /*@
40    PetscMemoryGetCurrentUsage - Returns the current resident set size (memory used)
41    for the program.
42 
43    Not Collective
44 
45    Output Parameter:
46 .   mem - memory usage in bytes
47 
48    Options Database Key:
49 .  -memory_info - Print memory usage at end of run
50 .  -malloc_log - Activate logging of memory usage
51 
52    Level: intermediate
53 
54    Notes:
55    The memory usage reported here includes all Fortran arrays
56    (that may be used in application-defined sections of code).
57    This routine thus provides a more complete picture of memory
58    usage than PetscMallocGetCurrentUsage() for codes that employ Fortran with
59    hardwired arrays.
60 
61 .seealso: PetscMallocGetMaximumUsage(), PetscMemoryGetMaximumUsage(), PetscMallocGetCurrentUsage()
62 
63    Concepts: resident set size
64    Concepts: memory usage
65 
66 @*/
67 PetscErrorCode  PetscMemoryGetCurrentUsage(PetscLogDouble *mem)
68 {
69 #if defined(PETSC_USE_PROCFS_FOR_SIZE)
70   FILE       *file;
71   int        fd;
72   char       proc[PETSC_MAX_PATH_LEN];
73   prpsinfo_t prusage;
74 #elif defined(PETSC_USE_SBREAK_FOR_SIZE)
75   long       *ii = sbreak(0);
76   int        fd  = ii - (long*)0;
77 #elif defined(PETSC_USE_PROC_FOR_SIZE) && defined(PETSC_HAVE_GETPAGESIZE)
78   FILE       *file;
79   char       proc[PETSC_MAX_PATH_LEN];
80   int        mm,rss,err;
81 #elif defined(PETSC_HAVE_TASK_INFO)
82   /*  task_basic_info_data_t ti;
83       unsigned int           count; */
84   /*
85      The next line defined variables that are not used; but if they
86      are not included the code crashes. Something must be wrong
87      with either the task_info() command or compiler corrupting the
88      stack.
89   */
90   /* kern_return_t          kerr; */
91 #elif defined(PETSC_HAVE_GETRUSAGE)
92   static struct rusage temp;
93 #endif
94 
95   PetscFunctionBegin;
96 #if defined(PETSC_USE_PROCFS_FOR_SIZE)
97 
98   sprintf(proc,"/proc/%d",(int)getpid());
99   if ((fd = open(proc,O_RDONLY)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to access system file %s to get memory usage data",file);
100   if (ioctl(fd,PIOCPSINFO,&prusage) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Unable to access system file %s to get memory usage data",file);
101   *mem = (PetscLogDouble)prusage.pr_byrssize;
102   close(fd);
103 
104 #elif defined(PETSC_USE_SBREAK_FOR_SIZE)
105 
106   *mem = (PetscLogDouble)(8*fd - 4294967296); /* 2^32 - upper bits */
107 
108 #elif defined(PETSC_USE_PROC_FOR_SIZE) && defined(PETSC_HAVE_GETPAGESIZE)
109   sprintf(proc,"/proc/%d/statm",(int)getpid());
110   if (!(file = fopen(proc,"r"))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to access system file %s to get memory usage data",proc);
111   if (fscanf(file,"%d %d",&mm,&rss) != 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"Failed to read two integers (mm and rss) from %s",proc);
112   *mem = ((PetscLogDouble)rss) * ((PetscLogDouble)getpagesize());
113   err  = fclose(file);
114   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
115 
116 #elif defined(PETSC_HAVE_TASK_INFO)
117   *mem = 0;
118   /* if ((kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&ti,&count)) != KERN_SUCCESS) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Mach system call failed: kern_return_t ",kerr);
119    *mem = (PetscLogDouble) ti.resident_size; */
120 
121 #elif defined(PETSC_HAVE_GETRUSAGE)
122   getrusage(RUSAGE_SELF,&temp);
123 #if defined(PETSC_USE_KBYTES_FOR_SIZE)
124   *mem = 1024.0 * ((PetscLogDouble)temp.ru_maxrss);
125 #elif defined(PETSC_HAVE_GETPAGESIZE)
126   *mem = ((PetscLogDouble)getpagesize())*((PetscLogDouble)temp.ru_maxrss);
127 #else
128   *mem = 0.0;
129 #endif
130 
131 #else
132   *mem = 0.0;
133 #endif
134   PetscFunctionReturn(0);
135 }
136 
137 PetscBool      PetscMemoryCollectMaximumUsage = PETSC_FALSE;
138 PetscLogDouble PetscMemoryMaximumUsage        = 0;
139 
140 #undef __FUNCT__
141 #define __FUNCT__ "PetscMemoryGetMaximumUsage"
142 /*@
143    PetscMemoryGetMaximumUsage - Returns the maximum resident set size (memory used)
144    for the program.
145 
146    Not Collective
147 
148    Output Parameter:
149 .   mem - memory usage in bytes
150 
151    Options Database Key:
152 .  -memory_info - Print memory usage at end of run
153 .  -malloc_log - Activate logging of memory usage
154 
155    Level: intermediate
156 
157    Notes:
158    The memory usage reported here includes all Fortran arrays
159    (that may be used in application-defined sections of code).
160    This routine thus provides a more complete picture of memory
161    usage than PetscMallocGetCurrentUsage() for codes that employ Fortran with
162    hardwired arrays.
163 
164 .seealso: PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), PetscMallocGetCurrentUsage(),
165           PetscMemorySetGetMaximumUsage()
166 
167    Concepts: resident set size
168    Concepts: memory usage
169 
170 @*/
171 PetscErrorCode  PetscMemoryGetMaximumUsage(PetscLogDouble *mem)
172 {
173   PetscFunctionBegin;
174   if (!PetscMemoryCollectMaximumUsage) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"To use this function you must first call PetscMemorySetGetMaximumUsage()");
175   *mem = PetscMemoryMaximumUsage;
176   PetscFunctionReturn(0);
177 }
178 
179 #undef __FUNCT__
180 #define __FUNCT__ "PetscMemorySetGetMaximumUsage"
181 /*@C
182    PetscMemorySetGetMaximumUsage - Tells PETSc to monitor the maximum memory usage so that
183        PetscMemoryGetMaximumUsage() will work.
184 
185    Not Collective
186 
187    Options Database Key:
188 .  -memory_info - Print memory usage at end of run
189 .  -malloc_log - Activate logging of memory usage
190 
191    Level: intermediate
192 
193 .seealso: PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(), PetscMallocGetCurrentUsage(),
194           PetscMemoryGetMaximumUsage()
195 
196    Concepts: resident set size
197    Concepts: memory usage
198 
199 @*/
200 PetscErrorCode  PetscMemorySetGetMaximumUsage(void)
201 {
202   PetscFunctionBegin;
203   PetscMemoryCollectMaximumUsage = PETSC_TRUE;
204   PetscFunctionReturn(0);
205 }
206