Skip to content

Commit c1bc52c

Browse files
committed
[Timer] On macOS count number of executed instructions
In addition to wall time etc. this should allow us to get less noisy values for time measurements.
1 parent 65e47e2 commit c1bc52c

File tree

5 files changed

+59
-16
lines changed

5 files changed

+59
-16
lines changed

clang-tools-extra/test/clang-tidy/infrastructure/clang-tidy-store-check-profile-one-tu.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
// CHECK-FILE-NEXT:"profile": {
1818
// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
1919
// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
20-
// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}
21-
// CHECK-FILE-NEXT: }
20+
// CHECK-FILE-NEXT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}{{,?}}
21+
// If available on the platform, we also have a "time.clang-tidy.readability-function-size.instr" entry
22+
// CHECK-FILE: }
2223
// CHECK-FILE-NEXT: }
2324

2425
// CHECK-FILE-NOT: {
@@ -27,7 +28,7 @@
2728
// CHECK-FILE-NOT: "profile": {
2829
// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.wall": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
2930
// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.user": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}},
30-
// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}
31+
// CHECK-FILE-NOT: "time.clang-tidy.readability-function-size.sys": {{.*}}{{[0-9]}}.{{[0-9]+}}e{{[-+]}}{{[0-9]}}{{[0-9]}}{{,?}}
3132
// CHECK-FILE-NOT: }
3233
// CHECK-FILE-NOT: }
3334

llvm/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,12 @@ else()
703703
endif()
704704
option(LLVM_ENABLE_PLUGINS "Enable plugin support" ${LLVM_ENABLE_PLUGINS_default})
705705

706+
include(CheckSymbolExists)
707+
check_symbol_exists(proc_pid_rusage "libproc.h" HAVE_PROC_PID_RUSAGE)
708+
if(HAVE_PROC_PID_RUSAGE)
709+
list(APPEND CMAKE_REQUIRED_LIBRARIES proc)
710+
endif()
711+
706712
set(ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER FALSE CACHE BOOL
707713
"Enable the experimental new pass manager by default.")
708714

llvm/include/llvm/Config/config.h.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,6 @@
350350
/* Whether Timers signpost passes in Xcode Instruments */
351351
#cmakedefine01 LLVM_SUPPORT_XCODE_SIGNPOSTS
352352

353+
#cmakedefine HAVE_PROC_PID_RUSAGE 1
354+
353355
#endif

llvm/include/llvm/Support/Timer.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ class TimerGroup;
2424
class raw_ostream;
2525

2626
class TimeRecord {
27-
double WallTime; ///< Wall clock time elapsed in seconds.
28-
double UserTime; ///< User time elapsed.
29-
double SystemTime; ///< System time elapsed.
30-
ssize_t MemUsed; ///< Memory allocated (in bytes).
27+
double WallTime; ///< Wall clock time elapsed in seconds.
28+
double UserTime; ///< User time elapsed.
29+
double SystemTime; ///< System time elapsed.
30+
ssize_t MemUsed; ///< Memory allocated (in bytes).
31+
uint64_t InstructionsExecuted; ///< Number of instructions executed
3132
public:
32-
TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
33+
TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0),
34+
InstructionsExecuted(0) {}
3335

3436
/// Get the current time and memory usage. If Start is true we get the memory
3537
/// usage before the time, otherwise we get time before memory usage. This
@@ -42,23 +44,26 @@ class TimeRecord {
4244
double getSystemTime() const { return SystemTime; }
4345
double getWallTime() const { return WallTime; }
4446
ssize_t getMemUsed() const { return MemUsed; }
47+
uint64_t getInstructionsExecuted() const { return InstructionsExecuted; }
4548

4649
bool operator<(const TimeRecord &T) const {
4750
// Sort by Wall Time elapsed, as it is the only thing really accurate
4851
return WallTime < T.WallTime;
4952
}
5053

5154
void operator+=(const TimeRecord &RHS) {
52-
WallTime += RHS.WallTime;
53-
UserTime += RHS.UserTime;
54-
SystemTime += RHS.SystemTime;
55-
MemUsed += RHS.MemUsed;
55+
WallTime += RHS.WallTime;
56+
UserTime += RHS.UserTime;
57+
SystemTime += RHS.SystemTime;
58+
MemUsed += RHS.MemUsed;
59+
InstructionsExecuted += RHS.InstructionsExecuted;
5660
}
5761
void operator-=(const TimeRecord &RHS) {
58-
WallTime -= RHS.WallTime;
59-
UserTime -= RHS.UserTime;
60-
SystemTime -= RHS.SystemTime;
61-
MemUsed -= RHS.MemUsed;
62+
WallTime -= RHS.WallTime;
63+
UserTime -= RHS.UserTime;
64+
SystemTime -= RHS.SystemTime;
65+
MemUsed -= RHS.MemUsed;
66+
InstructionsExecuted -= RHS.InstructionsExecuted;
6267
}
6368

6469
/// Print the current time record to \p OS, with a breakdown showing

llvm/lib/Support/Timer.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/Support/Timer.h"
1414
#include "llvm/ADT/Statistic.h"
1515
#include "llvm/ADT/StringMap.h"
16+
#include "llvm/Config/config.h"
1617
#include "llvm/Support/CommandLine.h"
1718
#include "llvm/Support/FileSystem.h"
1819
#include "llvm/Support/Format.h"
@@ -24,6 +25,14 @@
2425
#include "llvm/Support/raw_ostream.h"
2526
#include <limits>
2627

28+
#if HAVE_UNISTD_H
29+
#include <unistd.h>
30+
#endif
31+
32+
#ifdef HAVE_PROC_PID_RUSAGE
33+
#include <libproc.h>
34+
#endif
35+
2736
using namespace llvm;
2837

2938
// This ugly hack is brought to you courtesy of constructor/destructor ordering
@@ -120,6 +129,16 @@ static inline size_t getMemUsage() {
120129
return sys::Process::GetMallocUsage();
121130
}
122131

132+
static uint64_t getCurInstructionsExecuted() {
133+
#if defined(HAVE_UNISTD_H) && defined(HAVE_PROC_PID_RUSAGE) && defined(RUSAGE_INFO_V4)
134+
struct rusage_info_v4 ru;
135+
if (proc_pid_rusage(getpid(), RUSAGE_INFO_V4, (rusage_info_t *)&ru) == 0) {
136+
return ru.ri_instructions;
137+
}
138+
#endif
139+
return 0;
140+
}
141+
123142
TimeRecord TimeRecord::getCurrentTime(bool Start) {
124143
using Seconds = std::chrono::duration<double, std::ratio<1>>;
125144
TimeRecord Result;
@@ -128,9 +147,11 @@ TimeRecord TimeRecord::getCurrentTime(bool Start) {
128147

129148
if (Start) {
130149
Result.MemUsed = getMemUsage();
150+
Result.InstructionsExecuted = getCurInstructionsExecuted();
131151
sys::Process::GetTimeUsage(now, user, sys);
132152
} else {
133153
sys::Process::GetTimeUsage(now, user, sys);
154+
Result.InstructionsExecuted = getCurInstructionsExecuted();
134155
Result.MemUsed = getMemUsage();
135156
}
136157

@@ -180,6 +201,8 @@ void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
180201

181202
if (Total.getMemUsed())
182203
OS << format("%9" PRId64 " ", (int64_t)getMemUsed());
204+
if (Total.getInstructionsExecuted())
205+
OS << format("%9" PRId64 " ", (int64_t)getInstructionsExecuted());
183206
}
184207

185208

@@ -339,6 +362,8 @@ void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
339362
OS << " ---Wall Time---";
340363
if (Total.getMemUsed())
341364
OS << " ---Mem---";
365+
if (Total.getInstructionsExecuted())
366+
OS << " ---Instr---";
342367
OS << " --- Name ---\n";
343368

344369
// Loop through all of the timing data, printing it out.
@@ -433,6 +458,10 @@ const char *TimerGroup::printJSONValues(raw_ostream &OS, const char *delim) {
433458
OS << delim;
434459
printJSONValue(OS, R, ".mem", T.getMemUsed());
435460
}
461+
if (T.getInstructionsExecuted()) {
462+
OS << delim;
463+
printJSONValue(OS, R, ".instr", T.getInstructionsExecuted());
464+
}
436465
}
437466
TimersToPrint.clear();
438467
return delim;

0 commit comments

Comments
 (0)