2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2016 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/jit/timer.h"
24 #include <folly/Format.h>
26 #include "hphp/runtime/base/execution-context.h"
27 #include "hphp/util/timer.h"
28 #include "hphp/util/trace.h"
29 #include "hphp/util/vdso.h"
31 TRACE_SET_MOD(jittime
);
33 namespace HPHP
{ namespace jit
{
37 //////////////////////////////////////////////////////////////////////
39 __thread
Timer::Counter s_counters
[Timer::kNumTimers
];
41 struct TimerName
{ const char* str
; Timer::Name name
; };
42 const TimerName s_names
[] = {
43 # define TIMER_NAME(name) {#name, Timer::name},
48 int64_t getCPUTimeNanos() {
49 if (!RuntimeOption::EvalJitTimer
) return -1;
51 #ifdef CLOCK_THREAD_CPUTIME_ID
52 auto const ns
= Vdso::ClockGetTimeNS(CLOCK_THREAD_CPUTIME_ID
);
53 if (ns
!= -1) return ns
;
57 return HPHP::Timer::GetRusageMicros(HPHP::Timer::TotalCPU
,
58 HPHP::Timer::Thread
) * 1000;
64 //////////////////////////////////////////////////////////////////////
68 Timer::Timer(Name name
)
70 , m_start(getCPUTimeNanos())
76 if (!RuntimeOption::EvalJitTimer
|| m_finished
) return;
80 int64_t Timer::stop() {
81 if (!RuntimeOption::EvalJitTimer
) return 0;
84 auto const finish
= getCPUTimeNanos();
85 auto const elapsed
= finish
- m_start
;
87 auto& counter
= s_counters
[m_name
];
88 counter
.total
+= elapsed
;
90 counter
.max
= std::max(counter
.max
, elapsed
);
95 Timer::CounterVec
Timer::Counters() {
97 for (auto& pair
: s_names
) {
98 ret
.emplace_back(pair
.str
, s_counters
[pair
.name
]);
103 Timer::Counter
Timer::CounterValue(Timer::Name name
) {
104 return s_counters
[name
];
107 void Timer::RequestInit() {
108 memset(&s_counters
, 0, sizeof(s_counters
));
111 void Timer::RequestExit() {
116 if (!Trace::moduleEnabledRelease(Trace::jittime
)) return;
117 Trace::traceRelease("%s", Show().c_str());
120 std::string
Timer::Show() {
121 auto const header
= "{:<30} | {:>15} {:>15} {:>15} {:>15}\n";
122 auto const row
= "{:<30} | {:>15} {:>13,}us {:>13,}ns {:>13,}ns\n";
124 std::array
<TimerName
,kNumTimers
> names_copy
;
125 std::copy(s_names
, s_names
+ kNumTimers
, begin(names_copy
));
127 auto totalSort
= [] (const TimerName
& a
, const TimerName
& b
) {
128 return s_counters
[a
.name
].total
> s_counters
[b
.name
].total
;
130 auto nameSort
= [] (const TimerName
& a
, const TimerName
& b
) {
131 return strcmp(a
.str
, b
.str
) < 0;
134 begin(names_copy
), end(names_copy
),
135 getenv("HHVM_JIT_TIMER_NAME_SORT") ? nameSort
: totalSort
139 for (auto const& pair
: names_copy
) {
140 auto const& counter
= s_counters
[pair
.name
];
141 if (counter
.total
== 0 && counter
.count
== 0) continue;
148 counter
.total
/ 1000,
154 if (rows
.empty()) return rows
;
157 auto const url
= g_context
->getRequestUrl(75);
158 folly::format(&ret
, "\nJIT timers for {}\n", url
);
159 folly::format(&ret
, header
, "name", "count", "total", "average", "max");
160 folly::format(&ret
, "{:-^30}-+{:-^64}\n{}\n", "", "", rows
);