Add mode to EndCatch
[hiphop-php.git] / hphp / runtime / vm / type-profile.cpp
blob5ecf6f75cd0a8057228ac33612630ca38054e68d
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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/type-profile.h"
19 #include "hphp/runtime/base/execution-context.h"
20 #include "hphp/runtime/base/init-fini-node.h"
21 #include "hphp/runtime/base/request-info.h"
22 #include "hphp/runtime/base/runtime-option.h"
23 #include "hphp/runtime/base/stats.h"
24 #include "hphp/runtime/ext/server/ext_server.h"
25 #include "hphp/runtime/vm/func.h"
26 #include "hphp/runtime/vm/jit/mcgen-translate.h"
27 #include "hphp/runtime/vm/jit/relocation.h"
28 #include "hphp/runtime/vm/jit/tc.h"
29 #include "hphp/runtime/vm/jit/write-lease.h"
30 #include "hphp/runtime/vm/treadmill.h"
31 #include "hphp/util/atomic-vector.h"
32 #include "hphp/util/boot-stats.h"
33 #include "hphp/util/lock.h"
34 #include "hphp/util/logger.h"
35 #include "hphp/util/struct-log.h"
36 #include "hphp/util/trace.h"
38 #include <array>
39 #include <atomic>
40 #include <cstdint>
41 #include <queue>
42 #include <utility>
44 namespace HPHP {
46 TRACE_SET_MOD(typeProfile);
48 //////////////////////////////////////////////////////////////////////
51 * Warmup/profiling.
53 * In cli mode, we only record samples if we're in recording to replay later.
55 * In server mode, we exclude warmup document requests from profiling.
58 RDS_LOCAL_NO_CHECK(TypeProfileLocals, rl_typeProfileLocals)
59 {TypeProfileLocals{}};
61 namespace {
63 bool warmingUp;
64 std::atomic<int64_t> numRequests;
65 std::atomic<int> relocateRequests;
68 * RFH, or "requests served in first hour" is used as a performance metric that
69 * is affected by warmup speed as well as steady-state performance. For every
70 * element n in this list, we log a point along the RFH curve, which is the
71 * total number of requests served when server uptime hits n seconds.
73 constexpr std::array<uint32_t, 32> rfhBuckets = {{
74 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, // every 30s, to 5m
75 360, 420, 480, 540, 600, // every 1m, to 10m
76 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600, // every 5m, to 1h
77 4500, 5400, 6300, 7200, // every 15m, to 2h
78 3 * 3600, 4 * 3600, 6 * 3600
79 }};
80 std::atomic<size_t> nextRFH{0};
84 ProfileNonVMThread::ProfileNonVMThread() {
85 always_assert(!rl_typeProfileLocals->nonVMThread);
86 rl_typeProfileLocals->nonVMThread = true;
89 ProfileNonVMThread::~ProfileNonVMThread() {
90 rl_typeProfileLocals->nonVMThread = false;
93 void setRelocateRequests(int32_t n) {
94 relocateRequests.store(n);
97 void profileWarmupStart() {
98 warmingUp = true;
101 void profileWarmupEnd() {
102 warmingUp = false;
105 typedef std::pair<const Func*, uint32_t> FuncHotness;
106 static bool comp(const FuncHotness& a, const FuncHotness& b) {
107 return a.second > b.second;
110 int64_t requestCount() {
111 return numRequests.load(std::memory_order_relaxed);
114 static inline RequestKind getRequestKind() {
115 if (rl_typeProfileLocals->nonVMThread) return RequestKind::NonVM;
116 if (warmingUp) return RequestKind::Warmup;
117 return RequestKind::Standard;
120 void profileRequestStart() {
121 rl_typeProfileLocals->requestKind = getRequestKind();
123 // Force the request to use interpreter (not even running jitted code) during
124 // retranslateAll when we need to dump out precise profile data.
125 auto const forceInterp = jit::mcgen::pendingRetranslateAllScheduled() &&
126 RuntimeOption::DumpPreciseProfData;
127 bool okToJit = !forceInterp &&
128 (rl_typeProfileLocals->requestKind == RequestKind::Standard);
129 if (!RequestInfo::s_requestInfo.isNull()) {
130 if (RID().isJittingDisabled()) {
131 okToJit = false;
132 } else if (!okToJit) {
133 RID().setJittingDisabled(true);
136 jit::setMayAcquireLease(okToJit);
138 // Force interpretation if needed.
139 if (rl_typeProfileLocals->forceInterpret != forceInterp) {
140 rl_typeProfileLocals->forceInterpret = forceInterp;
141 if (!RequestInfo::s_requestInfo.isNull()) {
142 RID().updateJit();
146 if (okToJit && relocateRequests > 0 && !--relocateRequests) {
147 jit::tc::liveRelocate(true);
151 static void checkRFH(int64_t finished) {
152 auto i = nextRFH.load(std::memory_order_relaxed);
153 if (i == rfhBuckets.size() || !StructuredLog::enabled()) {
154 return;
157 auto const uptime = f_server_uptime();
158 if (uptime == -1) return;
159 assertx(uptime >= 0);
161 while (i < rfhBuckets.size() && uptime >= rfhBuckets[i]) {
162 assertx(i == 0 || rfhBuckets[i - 1] < rfhBuckets[i]);
163 if (!nextRFH.compare_exchange_strong(i, i + 1, std::memory_order_relaxed)) {
164 // Someone else reported the sample at i. Try again with the current
165 // value of nextRFH.
166 continue;
169 // "bucket" and "uptime" will always be the same as long as the server
170 // retires at least one request in each second of wall time.
171 StructuredLogEntry cols;
172 cols.setInt("requests", finished);
173 cols.setInt("bucket", rfhBuckets[i]);
174 cols.setInt("uptime", uptime);
175 StructuredLog::log("hhvm_rfh", cols);
177 ++i;
181 void profileRequestEnd() {
182 if (warmingUp ||
183 rl_typeProfileLocals->requestKind == RequestKind::NonVM) {
184 return;
186 auto const finished = numRequests.fetch_add(1, std::memory_order_relaxed) + 1;
187 static auto const requestSeries = ServiceData::createTimeSeries(
188 "vm.requests",
189 {ServiceData::StatsType::RATE, ServiceData::StatsType::SUM},
190 {std::chrono::seconds(60), std::chrono::seconds(0)}
192 requestSeries->addValue(1);
193 checkRFH(finished);