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
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
62namespace 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.
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)
128 /// enables print_meminfo() profiling
129 /// \note print_meminfo() profiling is on by default.
131 /// @return true if print_meminfo() will generate profiling data.
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
Macros and tools pertaining to the configuration of MADNESS.
const Char * Vm_cstr()
bool & print_meminfo_flag_accessor()
Definition worldmem.cc:184
const char * Vm_cstr< char >()
Definition worldmem.cc:181
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
static const char * filename
Definition legendre.cc:96
bool print_meminfo_enabled()
Definition worldmem.cc:200
WorldMemInfo * world_mem_info()
Returns pointer to internal structure.
Definition worldmem.cc:67
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_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
bool print_meminfo_keep_ostream_open()
Definition worldmem.cc:208
std::basic_ofstream< wchar_t > & print_meminfo_ostream(int rank, const std::string filename_prefix)
Definition worldmem.cc:213