Move io_tests to folly/io/async/test
[hiphop-php.git] / hphp / runtime / vm / jit / tc-info.cpp
blobc95eaf0e76a0e91fc6f164276a0e882135b4796e
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/jit/tc.h"
18 #include "hphp/runtime/vm/jit/tc-internal.h"
20 #include "hphp/runtime/base/rds.h"
21 #include "hphp/runtime/base/runtime-option.h"
23 #include "hphp/runtime/vm/runtime-compiler.h"
24 #include "hphp/runtime/vm/jit/code-cache.h"
25 #include "hphp/runtime/vm/jit/mcgen.h"
26 #include "hphp/runtime/vm/jit/prof-data.h"
27 #include "hphp/runtime/vm/jit/trans-db.h"
29 #include "hphp/util/data-block.h"
30 #include "hphp/util/build-info.h"
32 #include <folly/Format.h>
34 #include <algorithm>
35 #include <string>
36 #include <vector>
38 namespace HPHP::jit::tc {
40 namespace {
42 bool dumpTCCode(folly::StringPiece filename) {
43 #define OPEN_FILE(F, SUFFIX) \
44 auto const F ## name = folly::to<std::string>(filename, SUFFIX); \
45 FILE* F = fopen(F ## name .c_str(),"wb"); \
46 if (F == nullptr) return false; \
47 SCOPE_EXIT{ fclose(F); };
49 OPEN_FILE(aFile, "_a");
50 OPEN_FILE(acoldFile, "_acold");
51 OPEN_FILE(afrozenFile, "_afrozen");
53 #undef OPEN_FILE
55 // dump starting from the main region
56 auto result = true;
57 auto writeBlock = [&](const CodeBlock& cb, FILE* file) {
58 if (result) {
59 auto const count = cb.used();
60 result = fwrite(cb.base(), 1, count, file) == count;
64 writeBlock(code().main(), aFile);
65 writeBlock(code().cold(), acoldFile);
66 writeBlock(code().frozen(), afrozenFile);
67 return result;
70 bool dumpTCData() {
71 auto const dataPath = RuntimeOption::EvalDumpTCPath + "/tc_data.txt.gz";
72 gzFile tcDataFile = gzopen(dataPath.c_str(), "w");
73 if (!tcDataFile) return false;
74 SCOPE_EXIT { gzclose(tcDataFile); };
76 if (!gzprintf(tcDataFile,
77 "repo_schema = %s\n"
78 "a.base = %p\n"
79 "a.frontier = %p\n"
80 "acold.base = %p\n"
81 "acold.frontier = %p\n"
82 "afrozen.base = %p\n"
83 "afrozen.frontier = %p\n\n",
84 repoSchemaId().begin(),
85 code().main().base(), code().main().frontier(),
86 code().cold().base(), code().cold().frontier(),
87 code().frozen().base(), code().frozen().frontier())) {
88 return false;
91 if (!gzprintf(tcDataFile, "total_translations = %zu\n\n",
92 transdb::getNumTranslations())) {
93 return false;
96 // Print all translations, including their execution counters. If global
97 // counters are disabled (default), fall back to using ProfData, covering
98 // only profiling translations.
99 if (transdb::enabled()) {
100 // Admin requests do not automatically init ProfData, so do it explicitly.
101 // No need for matching exit call; data is immortal with trans DB enabled.
102 requestInitProfData();
104 const TransRec invalid;
105 assertx(!invalid.isValid());
106 for (TransID t = 0; t < transdb::getNumTranslations(); t++) {
107 auto transRec = transdb::getTransRec(t);
108 if (!transRec) transRec = &invalid;
109 auto const ret = gzputs(tcDataFile, transRec->print().c_str());
110 if (ret == -1) {
111 return false;
115 return true;
118 ////////////////////////////////////////////////////////////////////////////////
121 bool dumpEnabled() {
122 return RuntimeOption::EvalDumpTC ||
123 RuntimeOption::EvalDumpIR ||
124 RuntimeOption::EvalDumpRegion ||
125 RuntimeOption::EvalDumpInlDecision ||
126 RuntimeOption::EvalDumpCallTargets ||
127 RuntimeOption::EvalDumpLayoutCFG ||
128 RuntimeOption::EvalDumpVBC;
131 bool dump(bool ignoreLease /* = false */) {
132 if (!mcgen::initialized()) return false;
135 std::unique_lock<SimpleMutex> codeLock;
136 std::unique_lock<SimpleMutex> metaLock;
137 if (!ignoreLease) {
138 codeLock = lockCode();
139 metaLock = lockMetadata();
141 if (!dumpTCData()) return false;
142 if (!dumpTCCode(RO::EvalDumpTCPath + "/tc_dump")) return false;
145 if (!RO::RepoAuthoritative) {
146 dump_compiled_units(RO::EvalDumpTCPath + "/hhvm.hhbc");
149 return true;
152 std::vector<UsageInfo> getUsageInfo() {
153 std::vector<UsageInfo> tcUsageInfo;
155 code().forEachBlock([&] (const char* name, const CodeBlock& a) {
156 tcUsageInfo.emplace_back(UsageInfo{
157 std::string("code.") + name,
158 a.used(),
159 a.capacity(),
160 true
163 tcUsageInfo.emplace_back(UsageInfo{
164 "data",
165 code().data().used(),
166 code().data().capacity(),
167 true
169 tcUsageInfo.emplace_back(UsageInfo{
170 "RDS",
171 rds::usedBytes(),
172 RuntimeOption::EvalRDSSize * 3 / 4,
173 false
175 tcUsageInfo.emplace_back(UsageInfo{
176 "RDSLocal",
177 rds::usedLocalBytes(),
178 RuntimeOption::EvalRDSSize * 3 / 4,
179 false
181 tcUsageInfo.emplace_back(UsageInfo{
182 "persistentRDS",
183 rds::usedPersistentBytes(),
184 RuntimeOption::EvalRDSSize / 4,
185 false
187 return tcUsageInfo;
190 std::string getTCSpace() {
191 std::string usage;
192 size_t total_size = 0;
193 size_t total_capacity = 0;
195 auto const add_row = [&] (const UsageInfo& ui) {
196 auto const percent = ui.capacity ? 100 * ui.used / ui.capacity : 0;
198 usage += folly::format(
199 "mcg: {:9} bytes ({}%) in {}\n",
200 ui.used, percent, ui.name
201 ).str();
203 if (ui.global) {
204 total_size += ui.used;
205 total_capacity += ui.capacity;
209 auto const uis = getUsageInfo();
210 std::for_each(uis.begin(), uis.end(), add_row);
211 add_row(UsageInfo { "total", total_size, total_capacity, false });
213 return usage;
216 std::string getTCAddrs() {
217 std::string addrs;
219 code().forEachBlock([&] (const char* name, const CodeBlock& a) {
220 addrs += folly::format("{}: {}\n", name, a.base()).str();
222 return addrs;
225 std::vector<TCMemInfo> getTCMemoryUsage() {
226 std::vector<TCMemInfo> ret;
227 code().forEachBlock(
228 [&](const char* name, const CodeBlock& a) {
229 ret.emplace_back(TCMemInfo{
230 name,
231 a.used(),
232 a.numAllocs(),
233 a.numFrees(),
234 a.bytesFree(),
235 a.blocksFree()
239 return ret;