MADNESS  0.10.1
worldmem.h
Go to the documentation of this file.
1 #ifndef MADNESS_WORLD_WORLDMEM_H__INCLUDED
2 #define MADNESS_WORLD_WORLDMEM_H__INCLUDED
3 
4 /*
5  This file is part of MADNESS.
6 
7  Copyright (C) 2007,2010 Oak Ridge National Laboratory
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 
23  For more information please contact:
24 
25  Robert J. Harrison
26  Oak Ridge National Laboratory
27  One Bethel Valley Road
28  P.O. Box 2008, MS-6367
29 
30  email: harrisonrj@ornl.gov
31  tel: 865-241-3937
32  fax: 865-572-0680
33 
34 
35  $Id: world.cc 454 2008-01-26 03:08:15Z rjharrison $
36 */
37 
38 #include <madness/madness_config.h>
39 #include <string>
40 #ifdef WORLD_GATHER_MEM_STATS
41 #include <new>
42 #endif // WORLD_GATHER_MEM_STATS
43 #include <cstddef>
44 #include <fstream>
45 #include <sstream>
46 
47 #if defined(MADNESS_HAS_GOOGLE_PERF_TCMALLOC)
48 #include <gperftools/malloc_extension.h>
49 #elif defined(HAVE_IBMBGQ)
50 #include <spi/include/kernel/memory.h>
51 #elif defined(ON_A_MAC)
52 #include <malloc/malloc.h>
53 #elif defined(X86_32)
54 #include <malloc.h>
55 #elif defined(X86_64)
56 #include <sys/types.h>
57 #include <unistd.h>
58 #include <sys/sysinfo.h>
59 #include <string>
60 #endif
61 
62 namespace madness {
63 
64  /// Used to output memory statistics and control tracing, etc.
65 
66  /// There is currently only one instance of this class in worldmem.cc
67  /// that is used by special versions of global new+delete enabled
68  /// by compiling with WORLD_GATHER_MEM_STATS enabled.
69  ///
70  /// Default for max_mem_limit is unlimited.
71  class WorldMemInfo {
72 #ifdef WORLD_GATHER_MEM_STATS
73  friend void* ::operator new(size_t size) throw (std::bad_alloc);
74  friend void ::operator delete(void *p) throw();
75 #endif
76  private:
77  /// Invoked when user pointer p is allocated with size bytes
78  void do_new(void *p, std::size_t size);
79 
80  /// Invoked when user pointer p is deleted with size bytes
81  void do_del(void *p, std::size_t size);
82 
83  public:
84  static const unsigned long overhead = 4*sizeof(long) + 16;
85  /// If you add new stats be sure that the initialization in worldmem.cc is OK
86  unsigned long num_new_calls; ///< Counts calls to new
87  unsigned long num_del_calls; ///< Counts calls to delete
88  unsigned long cur_num_frags; ///< Current number of allocated fragments
89  unsigned long max_num_frags; ///< Lifetime maximum number of allocated fragments
90  unsigned long cur_num_bytes; ///< Current amount of allocated memory in bytes
91  unsigned long max_num_bytes; ///< Lifetime maximum number of allocated bytes
92  unsigned long max_mem_limit; ///< if size+cur_num_bytes>max_mem_limit new will throw MadnessException
93  bool trace;
94 
95  /// Prints memory use statistics to std::cout
96  void print() const;
97 
98  /// Resets all counters to zero
99  void reset();
100 
101  /// If trace is set true a message is printed for every new and delete
102  void set_trace(bool trace) {
103  this->trace = trace;
104  }
105 
106  /// Set the maximum memory limit (trying to allocate more will throw MadnessException)
107  void set_max_mem_limit(unsigned long max_mem_limit) {
108  this->max_mem_limit = max_mem_limit;
109  }
110  };
111 
112  /// Returns pointer to internal structure
113  WorldMemInfo* world_mem_info();
114 
115  namespace detail {
116  template <typename Char> const Char* Vm_cstr();
117 
119  }
120 
121  /// \name print_meminfo
122  /// These functions are useful to instrument *aggregate* (not fine-grained, like WorldMemInfo) memory profiling.
123  /// \note To make this functionality usable must set the `ENABLE_MEM_PROFILE` CMake cache variable to `ON`
124  ///@{
125 
126  /// disables print_meminfo() profiling (i.e. calling it is a no-op)
127  void print_meminfo_disable();
128  /// enables print_meminfo() profiling
129  /// \note print_meminfo() profiling is on by default.
130  void print_meminfo_enable();
131  /// @return true if print_meminfo() will generate profiling data.
132  bool print_meminfo_enabled();
133  /// @param[in] keep_open if true, the stream used by print_meminfo() will be
134  /// kept open
135  /// @note by default the stream is opened and closed every time
136  void print_meminfo_keep_ostream_open(bool keep_open);
137  /// @return true if the stream used by print_meminfo() is open between calls
139 
140  /// @param[in] rank process rank; the default is -1
141  /// @param[in] filename_prefix file name prefix; the default is empty string
142  /// @return open stream used by print_meminfo()
143  /// @throw std::runtime_error if:
144  /// - print_meminfo_keep_ostream_open() returns false, or
145  /// - called for the first time with default values of @p rank or
146  /// @p filename_prefix , or
147  /// - if this was previously called with different values of @p rank or
148  /// @p filename_prefix
149  std::basic_ofstream<wchar_t>& print_meminfo_ostream(
150  int rank = -1, const std::string filename_prefix = std::string(""));
151 
152  /// \brief print aggregate memory stats to file \c filename_prefix.<rank> , tagged with \c tag
153  /// \param[in] rank process rank
154  /// \param[in] tag record tag as any string type, e.g. \c const char[] , \c std::string , or \c std::wstring
155  /// \param[in] filename_prefix file name prefix; the default value is "MEMORY"
156  /// \param[in] verbose if true, will produce verbose output; is only currently used if TCMalloc is used
157  /// \note To make print_meminfo() usable must set the ENABLE_MEM_PROFILE CMake cache variable to ON; this makes print_meminfo() enabled by default.
158  /// To disable/enable programmatically use print_meminfo_disable()/print_meminfo_enable() .
159  /// \note must set global locale properly with \c std::locale::global() if \c tag has
160  /// nontrivial encoding
161  /// \warning this does not fence, it is up to the user to ensure proper synchronization
162  template <typename String> void print_meminfo(
163  int rank, const String& tag,
164  const std::string filename_prefix = std::string("MEMORY"),
165  bool verbose = false) {
166 #if defined(WORLD_MEM_PROFILE_ENABLE)
167  if (print_meminfo_enabled()) {
168  std::basic_ofstream<wchar_t> local_ofstream;
170  std::ostringstream filename;
171 
172  filename << filename_prefix << "." << rank;
173 
174  local_ofstream.open(filename.str().c_str(),
175  std::basic_ios<wchar_t>::out |
176  std::basic_ios<wchar_t>::app);
177  }
178  std::basic_ofstream<wchar_t>& memoryfile = print_meminfo_keep_ostream_open() ? print_meminfo_ostream(rank, filename_prefix) : local_ofstream;
179  if constexpr (std::is_same_v<String, std::basic_string<char>> || std::is_same_v<String, std::basic_string_view<char>>) {
180  std::wstring wtag; wtag.resize(tag.size());
181  std::copy(tag.begin(), tag.end(), wtag.begin());
182  memoryfile << wtag << std::endl;
183  }
184  else
185  memoryfile << tag << std::endl;
186 
187  const double to_MiB =
188  1 / (1024.0 * 1024.0); /* Convert from bytes to MiB */
189 #if defined(MADNESS_HAS_GOOGLE_PERF_TCMALLOC)
190  if (verbose) {
191  char buf[100000];
192  MallocExtension::instance()->GetStats(&buf[0], 100000);
193  memoryfile << buf << std::endl;
194  }
195  else { // <10000 => level-1 printing
196  char buf[9999];
197  MallocExtension::instance()->GetStats(&buf[0], 9999);
198  memoryfile << buf << std::endl;
199  }
200 #elif defined(HAVE_IBMBGQ)
201  uint64_t shared, persist, heapavail, stackavail, stack, heap, guard,
202  mmap;
203 
204  Kernel_GetMemorySize(KERNEL_MEMSIZE_SHARED, &shared);
205  Kernel_GetMemorySize(KERNEL_MEMSIZE_PERSIST, &persist);
206  Kernel_GetMemorySize(KERNEL_MEMSIZE_HEAPAVAIL, &heapavail);
207  Kernel_GetMemorySize(KERNEL_MEMSIZE_STACKAVAIL, &stackavail);
208  Kernel_GetMemorySize(KERNEL_MEMSIZE_STACK, &stack);
209  Kernel_GetMemorySize(KERNEL_MEMSIZE_HEAP, &heap);
210  Kernel_GetMemorySize(KERNEL_MEMSIZE_GUARD, &guard);
211  Kernel_GetMemorySize(KERNEL_MEMSIZE_MMAP, &mmap);
212 
213  memoryfile << "Heap size (MiB): " << (heap * to_MiB)
214  << ", available: " << (heapavail * to_MiB) << std::endl;
215  memoryfile << "Stack size (MiB): " << (stack * to_MiB)
216  << ", available: " << (stackavail * to_MiB) << std::endl;
217  memoryfile << "Memory (MiB): shared: " << (shared * to_MiB)
218  << ", persist: " << (persist * to_MiB)
219  << ", guard: " << (guard * to_MiB) << ", mmap: " << (mmap * to_MiB)
220  << std::endl;
221 #elif defined(ON_A_MAC)
222  /* Mac OS X specific hack - un-tested post Snow Leopard */
223  struct malloc_statistics_t mi; /* structure in bytes */
224 
225  malloc_zone_statistics(nullptr, &mi);
226 
227  memoryfile << "Heap allocated (MiB): " << (mi.size_allocated * to_MiB) << std::endl;
228  memoryfile << "Heap used (MiB): " << (mi.size_in_use * to_MiB) << std::endl;
229  memoryfile << "Heap max used (MiB): " << (mi.max_size_in_use * to_MiB) << std::endl;
230 #elif defined(X86_32) // 32-bit Linux
231  struct mallinfo mi; /* structure in bytes */
232 
233  mi = mallinfo();
234 
235  memoryfile << "Non-mmap (MiB): " << (mi.arena * to_MiB) << std::endl;
236  memoryfile << "Mmap (MiB): " << (mi.hblkhd * to_MiB) << std::endl;
237  memoryfile << "Total malloc chunks (MiB): " << (mi.uordblks * to_MiB)
238  << std::endl;
239 #elif defined(X86_64) // 64-bit Linux
240  // try parsing /proc/PID/status first, fallback on sysinfo
241  std::string status_fname =
242  std::string("/proc/") + std::to_string(getpid()) + std::string("/status");
243  std::basic_ifstream<char> status_stream(status_fname);
244  if (status_stream.good()) {
245  std::basic_string<char> line;
246  while (std::getline(status_stream, line)) {
247  if (line.find(detail::Vm_cstr<char>()) == 0)
248  memoryfile << line.c_str() << std::endl;
249  }
250  status_stream.close();
251  } else {
252  /* Better than nothing, mallinfo unreliable on 64-bit machine due to
253  use of int in mallinfo data structure. Requires Linux
254  kernel. Inaccurate if other processes besides MADNESS are
255  running. Memory differences appear to be reliable. */
256  struct sysinfo si; /* structure in bytes */
257 
258  sysinfo(&si);
259 
260  memoryfile << "Total RAM (MiB): " << (si.totalram * to_MiB) << std::endl;
261  memoryfile << "Free RAM (MiB): " << (si.freeram * to_MiB) << std::endl;
262  memoryfile << "Buffer (MiB): " << (si.bufferram * to_MiB) << std::endl;
263  memoryfile << "RAM in use (MiB): "
264  << ((si.totalram - si.freeram + si.bufferram) * to_MiB)
265  << std::endl;
266  }
267 #endif // platform specific
269  memoryfile.close();
270  }
271  }
272 #else // WORLD_MEM_PROFILE_ENABLE
273  return;
274 #endif // WORLD_MEM_PROFILE_ENABLE
275  }
276 
277  ///@}
278 
279 } // namespace madness
280 
281 #endif // MADNESS_WORLD_WORLDMEM_H__INCLUDED
Used to output memory statistics and control tracing, etc.
Definition: worldmem.h:71
void print() const
Prints memory use statistics to std::cout.
Definition: worldmem.cc:91
void reset()
Resets all counters to zero.
Definition: worldmem.cc:105
void set_trace(bool trace)
If trace is set true a message is printed for every new and delete.
Definition: worldmem.h:102
void set_max_mem_limit(unsigned long max_mem_limit)
Set the maximum memory limit (trying to allocate more will throw MadnessException)
Definition: worldmem.h:107
unsigned long num_new_calls
If you add new stats be sure that the initialization in worldmem.cc is OK.
Definition: worldmem.h:86
void do_del(void *p, std::size_t size)
Invoked when user pointer p is deleted with size bytes.
Definition: worldmem.cc:82
unsigned long cur_num_bytes
Current amount of allocated memory in bytes.
Definition: worldmem.h:90
void do_new(void *p, std::size_t size)
Invoked when user pointer p is allocated with size bytes.
Definition: worldmem.cc:71
unsigned long max_num_frags
Lifetime maximum number of allocated fragments.
Definition: worldmem.h:89
unsigned long cur_num_frags
Current number of allocated fragments.
Definition: worldmem.h:88
unsigned long num_del_calls
Counts calls to delete.
Definition: worldmem.h:87
unsigned long max_mem_limit
if size+cur_num_bytes>max_mem_limit new will throw MadnessException
Definition: worldmem.h:92
static const unsigned long overhead
Definition: worldmem.h:84
unsigned long max_num_bytes
Lifetime maximum number of allocated bytes.
Definition: worldmem.h:91
bool trace
Definition: worldmem.h:93
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition: derivatives.cc:72
Fcwf copy(Fcwf psi)
Definition: fcwf.cc:338
Macros and tools pertaining to the configuration of MADNESS.
const char * Vm_cstr< char >()
Definition: worldmem.cc:181
const Char * Vm_cstr()
bool & print_meminfo_flag_accessor()
Definition: worldmem.cc:184
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
WorldMemInfo * world_mem_info()
Returns pointer to internal structure.
Definition: worldmem.cc:67
static const char * filename
Definition: legendre.cc:96
bool print_meminfo_enabled()
Definition: worldmem.cc:200
std::basic_ofstream< wchar_t > & print_meminfo_ostream(int rank, const std::string filename_prefix)
Definition: worldmem.cc:213
void print_meminfo(int rank, const String &tag, const std::string filename_prefix=std::string("MEMORY"), bool verbose=false)
print aggregate memory stats to file filename_prefix.<rank> , tagged with tag
Definition: worldmem.h:162
void print_meminfo_keep_ostream_open(bool keep_open)
Definition: worldmem.cc:204
void print_meminfo_disable()
disables print_meminfo() profiling (i.e. calling it is a no-op)
Definition: worldmem.cc:194
void print_meminfo_enable()
Definition: worldmem.cc:197