LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
MallocOpts.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Utilities
4 // Class : MallocOpts
5 //
6 // Original Author: Jim Kowalkowski
7 //
8 //
9 // ------------------ resetting malloc options -----------------------
10 
12 
13 #if !defined(__APPLE__)
14 #include <malloc.h>
15 #endif
16 #include <cstdlib>
17 #include <cstring>
18 #include <iostream>
19 #include <sstream>
20 
21 namespace art {
22 
23  std::ostream&
24  operator<<(std::ostream& ost, const MallocOpts& opts)
25  {
26  ost << "mmap_max=" << opts.mmap_max_ << " trim_threshold=" << opts.trim_thr_
27  << " top_padding=" << opts.top_pad_
28  << " mmap_threshold=" << opts.mmap_thr_;
29  return ost;
30  }
31 
32  namespace {
33  enum cpu_type { UNKNOWN_CPU = 0, AMD_CPU = 1, INTEL_CPU = 2 };
34 
35  cpu_type
36  get_cpu_type()
37  {
38  // issue: these need to be static. The asm instruction combined
39  // with optimization on the 64 bit platform moves the stack data
40  // member around in such a way that the =m directive misses the
41  // the location. Of course this means that this routine is not
42  // multithread safe.
43  static volatile int op = 0, a;
44  static volatile int ans[4];
45 
46 // Still some problem on x86_64, so only i386 for now
47 #if defined(__x86_64__)
48 
49  __asm__ __volatile__("pushq %%rdx;\
50  pushq %%rcx; \
51  pushq %%rsi; \
52  pushq %%rbx; \
53  cpuid; \
54  movq %%rbx,%%rsi; \
55  popq %%rbx; \
56  movl %%ecx,%0; \
57  movl %%edx,%1; \
58  movl %%esi,%2; \
59  movl %%eax,%3; \
60  popq %%rsi; \
61  popq %%rcx; \
62  popq %%rdx;"
63  : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
64  : "a"(op));
65 
66 #elif defined(__i386__)
67 
68  __asm__ __volatile__("pushl %%edx;\
69  pushl %%ecx; \
70  pushl %%esi; \
71  pushl %%ebx; \
72  cpuid; \
73  movl %%ebx,%%esi; \
74  popl %%ebx; \
75  movl %%ecx,%0; \
76  movl %%edx,%1; \
77  movl %%esi,%2; \
78  movl %%eax,%3; \
79  popl %%esi; \
80  popl %%ecx; \
81  popl %%edx;"
82  : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
83  : "a"(op));
84 
85 #else
86  const char* unknown_str = "Unknown";
87  // int unknown_sz = strlen(unknown_str);
88  strcpy((char*)&ans[0], unknown_str);
89 #endif
90 
91  const char* amd_str = "AuthenticAMD";
92  int amd_sz = strlen(amd_str);
93  const char* intel_str = "GenuineIntel";
94  int intel_sz = strlen(intel_str);
95 
96  char* str = (char*)&ans[0];
97  ans[3] = 0;
98 
99  return strncmp(str, amd_str, amd_sz) == 0 ? AMD_CPU :
100  strncmp(str, intel_str, intel_sz) == 0 ? INTEL_CPU :
101  UNKNOWN_CPU;
102  }
103 
104  // values determined experimentally for each architecture
105  const MallocOpts intel_opts(262144, 524288, 5242880, 131072);
106  const MallocOpts amd_opts(0, 8388608, 131072, 10485760);
107 
108  } // namespace
109 
110  bool
112  {
113  bool rc = true;
114 
115  switch (get_cpu_type()) {
116  case AMD_CPU: {
117  values_ = amd_opts;
118  changed_ = true;
119  break;
120  }
121  case INTEL_CPU: {
122  values_ = intel_opts;
123  changed_ = true;
124  break;
125  }
126  case UNKNOWN_CPU:
127  default:
128  rc = false;
129  }
130 
131  return rc;
132  }
133 
135  {
138  if (hasErrors()) {
139  std::cerr << "ERROR: Reset of malloc options has fails:\n"
140  << error_message_ << '\n';
141  }
142  }
143  }
144 
145  void
147  {
148  if (changed_ == false)
149  return; // only adjust if they changed
150  error_message_.clear();
151  changed_ = false;
152 
153 #ifdef M_MMAP_MAX
154  if (mallopt(M_MMAP_MAX, values_.mmap_max_) < 0)
155  error_message_ += "Could not set M_MMAP_MAX\n";
156 #endif
157 #ifdef M_TRIM_THRESHOLD
158  if (mallopt(M_TRIM_THRESHOLD, values_.trim_thr_) < 0)
159  error_message_ += "Could not set M_TRIM_THRESHOLD\n";
160 #endif
161 #ifdef M_TOP_PAD
162  if (mallopt(M_TOP_PAD, values_.top_pad_) < 0)
163  error_message_ += "ERROR: Could not set M_TOP_PAD\n";
164 #endif
165 #ifdef M_MMAP_THRESHOLD
166  if (mallopt(M_MMAP_THRESHOLD, values_.mmap_thr_) < 0)
167  error_message_ += "ERROR: Could not set M_MMAP_THRESHOLD\n";
168 #endif
169  }
170 
171  bool
173  {
174  const char* par = getenv("ART_MALLOC_RESET");
175  if (par == 0)
176  return false; // leave quickly here
177  std::string spar(par);
178  bool rc = false;
179 
180  if (spar.size() > 1) {
181  std::istringstream ist(spar);
184 
185  if (ist.bad()) {
186  std::cerr
187  << "bad malloc options in ART_MALLOC_RESET: " << spar << '\n'
188  << "format is: "
189  << "ART_MALLOC_RESET=\"mmap_max trim_thres top_pad mmap_thres\"\n";
190  } else {
191  std::cout << "MALLOC_OPTIONS> Reset options: "
192  << "ART_MALLOC_RESET=" << par << '\n';
193  }
194  rc = true;
195  changed_ = true;
196  }
197 
198  return rc;
199  }
200 
201 } // namespace art
opt_type mmap_max_
Definition: MallocOpts.h:41
opt_type top_pad_
Definition: MallocOpts.h:43
opt_type mmap_thr_
Definition: MallocOpts.h:44
std::string error_message_
Definition: MallocOpts.h:115
bool hasErrors() const
Definition: MallocOpts.h:70
std::ostream & operator<<(std::ostream &os, const GroupSelector &gs)
opt_type trim_thr_
Definition: MallocOpts.h:42
Definition: MVAAlg.h:12