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