~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/Support/Timer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- Timer.cpp - Interval Timing Support -------------------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open Source
 
6
// License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
//
 
10
// Interval Timing implementation.
 
11
//
 
12
//===----------------------------------------------------------------------===//
 
13
 
 
14
#include "llvm/Support/Debug.h"
 
15
#include "llvm/Support/Timer.h"
 
16
#include "llvm/Support/CommandLine.h"
 
17
#include "llvm/Support/ManagedStatic.h"
 
18
#include "llvm/Support/raw_ostream.h"
 
19
#include "llvm/Support/Format.h"
 
20
#include "llvm/System/Process.h"
 
21
#include <algorithm>
 
22
#include <functional>
 
23
#include <map>
 
24
using namespace llvm;
 
25
 
 
26
// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
 
27
namespace llvm { extern raw_ostream *GetLibSupportInfoOutputFile(); }
 
28
 
 
29
// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
 
30
// of constructor/destructor ordering being unspecified by C++.  Basically the
 
31
// problem is that a Statistic object gets destroyed, which ends up calling
 
32
// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
 
33
// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
 
34
// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
 
35
// this by creating the string the first time it is needed and never destroying
 
36
// it.
 
37
static ManagedStatic<std::string> LibSupportInfoOutputFilename;
 
38
static std::string &getLibSupportInfoOutputFilename() {
 
39
  return *LibSupportInfoOutputFilename;
 
40
}
 
41
 
 
42
static ManagedStatic<sys::SmartMutex<true> > TimerLock;
 
43
 
 
44
namespace {
 
45
  static cl::opt<bool>
 
46
  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
 
47
                                      "tracking (this may be slow)"),
 
48
             cl::Hidden);
 
49
 
 
50
  static cl::opt<std::string, true>
 
51
  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
 
52
                     cl::desc("File to append -stats and -timer output to"),
 
53
                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
 
54
}
 
55
 
 
56
static TimerGroup *DefaultTimerGroup = 0;
 
57
static TimerGroup *getDefaultTimerGroup() {
 
58
  TimerGroup* tmp = DefaultTimerGroup;
 
59
  sys::MemoryFence();
 
60
  if (!tmp) {
 
61
    llvm_acquire_global_lock();
 
62
    tmp = DefaultTimerGroup;
 
63
    if (!tmp) {
 
64
      tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
 
65
      sys::MemoryFence();
 
66
      DefaultTimerGroup = tmp;
 
67
    }
 
68
    llvm_release_global_lock();
 
69
  }
 
70
 
 
71
  return tmp;
 
72
}
 
73
 
 
74
Timer::Timer(const std::string &N)
 
75
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
 
76
    Started(false), TG(getDefaultTimerGroup()) {
 
77
  TG->addTimer();
 
78
}
 
79
 
 
80
Timer::Timer(const std::string &N, TimerGroup &tg)
 
81
  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
 
82
    Started(false), TG(&tg) {
 
83
  TG->addTimer();
 
84
}
 
85
 
 
86
Timer::Timer(const Timer &T) {
 
87
  TG = T.TG;
 
88
  if (TG) TG->addTimer();
 
89
  operator=(T);
 
90
}
 
91
 
 
92
 
 
93
// Copy ctor, initialize with no TG member.
 
94
Timer::Timer(bool, const Timer &T) {
 
95
  TG = T.TG;     // Avoid assertion in operator=
 
96
  operator=(T);  // Copy contents
 
97
  TG = 0;
 
98
}
 
99
 
 
100
 
 
101
Timer::~Timer() {
 
102
  if (TG) {
 
103
    if (Started) {
 
104
      Started = false;
 
105
      TG->addTimerToPrint(*this);
 
106
    }
 
107
    TG->removeTimer();
 
108
  }
 
109
}
 
110
 
 
111
static inline size_t getMemUsage() {
 
112
  if (TrackSpace)
 
113
    return sys::Process::GetMallocUsage();
 
114
  return 0;
 
115
}
 
116
 
 
117
struct TimeRecord {
 
118
  double Elapsed, UserTime, SystemTime;
 
119
  ssize_t MemUsed;
 
120
};
 
121
 
 
122
static TimeRecord getTimeRecord(bool Start) {
 
123
  TimeRecord Result;
 
124
 
 
125
  sys::TimeValue now(0,0);
 
126
  sys::TimeValue user(0,0);
 
127
  sys::TimeValue sys(0,0);
 
128
 
 
129
  ssize_t MemUsed = 0;
 
130
  if (Start) {
 
131
    MemUsed = getMemUsage();
 
132
    sys::Process::GetTimeUsage(now,user,sys);
 
133
  } else {
 
134
    sys::Process::GetTimeUsage(now,user,sys);
 
135
    MemUsed = getMemUsage();
 
136
  }
 
137
 
 
138
  Result.Elapsed  = now.seconds()  + now.microseconds()  / 1000000.0;
 
139
  Result.UserTime = user.seconds() + user.microseconds() / 1000000.0;
 
140
  Result.SystemTime  = sys.seconds()  + sys.microseconds()  / 1000000.0;
 
141
  Result.MemUsed  = MemUsed;
 
142
 
 
143
  return Result;
 
144
}
 
145
 
 
146
static ManagedStatic<std::vector<Timer*> > ActiveTimers;
 
147
 
 
148
void Timer::startTimer() {
 
149
  sys::SmartScopedLock<true> L(*TimerLock);
 
150
  Started = true;
 
151
  ActiveTimers->push_back(this);
 
152
  TimeRecord TR = getTimeRecord(true);
 
153
  Elapsed    -= TR.Elapsed;
 
154
  UserTime   -= TR.UserTime;
 
155
  SystemTime -= TR.SystemTime;
 
156
  MemUsed    -= TR.MemUsed;
 
157
  PeakMemBase = TR.MemUsed;
 
158
}
 
159
 
 
160
void Timer::stopTimer() {
 
161
  sys::SmartScopedLock<true> L(*TimerLock);
 
162
  TimeRecord TR = getTimeRecord(false);
 
163
  Elapsed    += TR.Elapsed;
 
164
  UserTime   += TR.UserTime;
 
165
  SystemTime += TR.SystemTime;
 
166
  MemUsed    += TR.MemUsed;
 
167
 
 
168
  if (ActiveTimers->back() == this) {
 
169
    ActiveTimers->pop_back();
 
170
  } else {
 
171
    std::vector<Timer*>::iterator I =
 
172
      std::find(ActiveTimers->begin(), ActiveTimers->end(), this);
 
173
    assert(I != ActiveTimers->end() && "stop but no startTimer?");
 
174
    ActiveTimers->erase(I);
 
175
  }
 
176
}
 
177
 
 
178
void Timer::sum(const Timer &T) {
 
179
  Elapsed    += T.Elapsed;
 
180
  UserTime   += T.UserTime;
 
181
  SystemTime += T.SystemTime;
 
182
  MemUsed    += T.MemUsed;
 
183
  PeakMem    += T.PeakMem;
 
184
}
 
185
 
 
186
/// addPeakMemoryMeasurement - This method should be called whenever memory
 
187
/// usage needs to be checked.  It adds a peak memory measurement to the
 
188
/// currently active timers, which will be printed when the timer group prints
 
189
///
 
190
void Timer::addPeakMemoryMeasurement() {
 
191
  sys::SmartScopedLock<true> L(*TimerLock);
 
192
  size_t MemUsed = getMemUsage();
 
193
 
 
194
  for (std::vector<Timer*>::iterator I = ActiveTimers->begin(),
 
195
         E = ActiveTimers->end(); I != E; ++I)
 
196
    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
 
197
}
 
198
 
 
199
//===----------------------------------------------------------------------===//
 
200
//   NamedRegionTimer Implementation
 
201
//===----------------------------------------------------------------------===//
 
202
 
 
203
namespace {
 
204
 
 
205
typedef std::map<std::string, Timer> Name2Timer;
 
206
typedef std::map<std::string, std::pair<TimerGroup, Name2Timer> > Name2Pair;
 
207
 
 
208
}
 
209
 
 
210
static ManagedStatic<Name2Timer> NamedTimers;
 
211
 
 
212
static ManagedStatic<Name2Pair> NamedGroupedTimers;
 
213
 
 
214
static Timer &getNamedRegionTimer(const std::string &Name) {
 
215
  sys::SmartScopedLock<true> L(*TimerLock);
 
216
  Name2Timer::iterator I = NamedTimers->find(Name);
 
217
  if (I != NamedTimers->end())
 
218
    return I->second;
 
219
 
 
220
  return NamedTimers->insert(I, std::make_pair(Name, Timer(Name)))->second;
 
221
}
 
222
 
 
223
static Timer &getNamedRegionTimer(const std::string &Name,
 
224
                                  const std::string &GroupName) {
 
225
  sys::SmartScopedLock<true> L(*TimerLock);
 
226
 
 
227
  Name2Pair::iterator I = NamedGroupedTimers->find(GroupName);
 
228
  if (I == NamedGroupedTimers->end()) {
 
229
    TimerGroup TG(GroupName);
 
230
    std::pair<TimerGroup, Name2Timer> Pair(TG, Name2Timer());
 
231
    I = NamedGroupedTimers->insert(I, std::make_pair(GroupName, Pair));
 
232
  }
 
233
 
 
234
  Name2Timer::iterator J = I->second.second.find(Name);
 
235
  if (J == I->second.second.end())
 
236
    J = I->second.second.insert(J,
 
237
                                std::make_pair(Name,
 
238
                                               Timer(Name,
 
239
                                                     I->second.first)));
 
240
 
 
241
  return J->second;
 
242
}
 
243
 
 
244
NamedRegionTimer::NamedRegionTimer(const std::string &Name)
 
245
  : TimeRegion(getNamedRegionTimer(Name)) {}
 
246
 
 
247
NamedRegionTimer::NamedRegionTimer(const std::string &Name,
 
248
                                   const std::string &GroupName)
 
249
  : TimeRegion(getNamedRegionTimer(Name, GroupName)) {}
 
250
 
 
251
//===----------------------------------------------------------------------===//
 
252
//   TimerGroup Implementation
 
253
//===----------------------------------------------------------------------===//
 
254
 
 
255
 
 
256
static void printVal(double Val, double Total, raw_ostream &OS) {
 
257
  if (Total < 1e-7)   // Avoid dividing by zero...
 
258
    OS << "        -----     ";
 
259
  else {
 
260
    OS << "  " << format("%7.4f", Val) << " (";
 
261
    OS << format("%5.1f", Val*100/Total) << "%)";
 
262
  }
 
263
}
 
264
 
 
265
void Timer::print(const Timer &Total, raw_ostream &OS) {
 
266
  sys::SmartScopedLock<true> L(*TimerLock);
 
267
  if (Total.UserTime)
 
268
    printVal(UserTime, Total.UserTime, OS);
 
269
  if (Total.SystemTime)
 
270
    printVal(SystemTime, Total.SystemTime, OS);
 
271
  if (Total.getProcessTime())
 
272
    printVal(getProcessTime(), Total.getProcessTime(), OS);
 
273
  printVal(Elapsed, Total.Elapsed, OS);
 
274
 
 
275
  OS << "  ";
 
276
 
 
277
  if (Total.MemUsed) {
 
278
    OS << format("%9lld", (long long)MemUsed) << "  ";
 
279
  }
 
280
  if (Total.PeakMem) {
 
281
    if (PeakMem) {
 
282
      OS << format("%9lld", (long long)PeakMem) << "  ";
 
283
    } else
 
284
      OS << "           ";
 
285
  }
 
286
  OS << Name << "\n";
 
287
 
 
288
  Started = false;  // Once printed, don't print again
 
289
}
 
290
 
 
291
// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
 
292
raw_ostream *
 
293
llvm::GetLibSupportInfoOutputFile() {
 
294
  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
 
295
  if (LibSupportInfoOutputFilename.empty())
 
296
    return &errs();
 
297
  if (LibSupportInfoOutputFilename == "-")
 
298
    return &outs();
 
299
 
 
300
 
 
301
  std::string Error;
 
302
  raw_ostream *Result = new raw_fd_ostream(LibSupportInfoOutputFilename.c_str(),
 
303
                                           Error, raw_fd_ostream::F_Append);
 
304
  if (Error.empty())
 
305
    return Result;
 
306
 
 
307
  errs() << "Error opening info-output-file '"
 
308
         << LibSupportInfoOutputFilename << " for appending!\n";
 
309
  delete Result;
 
310
  return &errs();
 
311
}
 
312
 
 
313
 
 
314
void TimerGroup::removeTimer() {
 
315
  sys::SmartScopedLock<true> L(*TimerLock);
 
316
  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
 
317
    // Sort the timers in descending order by amount of time taken...
 
318
    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
 
319
              std::greater<Timer>());
 
320
 
 
321
    // Figure out how many spaces to indent TimerGroup name...
 
322
    unsigned Padding = (80-Name.length())/2;
 
323
    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
 
324
 
 
325
    raw_ostream *OutStream = GetLibSupportInfoOutputFile();
 
326
 
 
327
    ++NumTimers;
 
328
    {  // Scope to contain Total timer... don't allow total timer to drop us to
 
329
       // zero timers...
 
330
      Timer Total("TOTAL");
 
331
 
 
332
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
 
333
        Total.sum(TimersToPrint[i]);
 
334
 
 
335
      // Print out timing header...
 
336
      *OutStream << "===" << std::string(73, '-') << "===\n"
 
337
                 << std::string(Padding, ' ') << Name << "\n"
 
338
                 << "===" << std::string(73, '-')
 
339
                 << "===\n";
 
340
 
 
341
      // If this is not an collection of ungrouped times, print the total time.
 
342
      // Ungrouped timers don't really make sense to add up.  We still print the
 
343
      // TOTAL line to make the percentages make sense.
 
344
      if (this != DefaultTimerGroup) {
 
345
        *OutStream << "  Total Execution Time: ";
 
346
 
 
347
        *OutStream << format("%5.4f", Total.getProcessTime()) << " seconds (";
 
348
        *OutStream << format("%5.4f", Total.getWallTime()) << " wall clock)\n";
 
349
      }
 
350
      *OutStream << "\n";
 
351
 
 
352
      if (Total.UserTime)
 
353
        *OutStream << "   ---User Time---";
 
354
      if (Total.SystemTime)
 
355
        *OutStream << "   --System Time--";
 
356
      if (Total.getProcessTime())
 
357
        *OutStream << "   --User+System--";
 
358
      *OutStream << "   ---Wall Time---";
 
359
      if (Total.getMemUsed())
 
360
        *OutStream << "  ---Mem---";
 
361
      if (Total.getPeakMem())
 
362
        *OutStream << "  -PeakMem-";
 
363
      *OutStream << "  --- Name ---\n";
 
364
 
 
365
      // Loop through all of the timing data, printing it out...
 
366
      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
 
367
        TimersToPrint[i].print(Total, *OutStream);
 
368
 
 
369
      Total.print(Total, *OutStream);
 
370
      *OutStream << '\n';
 
371
      OutStream->flush();
 
372
    }
 
373
    --NumTimers;
 
374
 
 
375
    TimersToPrint.clear();
 
376
 
 
377
    if (OutStream != &errs() && OutStream != &outs() && OutStream != &dbgs())
 
378
      delete OutStream;   // Close the file...
 
379
  }
 
380
}
 
381
 
 
382
void TimerGroup::addTimer() {
 
383
  sys::SmartScopedLock<true> L(*TimerLock);
 
384
  ++NumTimers;
 
385
}
 
386
 
 
387
void TimerGroup::addTimerToPrint(const Timer &T) {
 
388
  sys::SmartScopedLock<true> L(*TimerLock);
 
389
  TimersToPrint.push_back(Timer(true, T));
 
390
}
 
391