track total size of static array and Unit/Class/Func
[hiphop-php.git] / hphp / runtime / server / warmup-request-handler.cpp
blob1612859996a8037cab3f964e3fdba8aae441c43d
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/server/warmup-request-handler.h"
19 #include "hphp/runtime/base/memory-manager.h"
20 #include "hphp/runtime/base/program-functions.h"
21 #include "hphp/runtime/ext/server/ext_server.h"
22 #include "hphp/runtime/vm/jit/mcgen-translate.h"
23 #include "hphp/runtime/server/http-server.h"
24 #include "hphp/runtime/server/replay-transport.h"
26 #include "hphp/util/boot-stats.h"
27 #include "hphp/util/hash-map.h"
28 #include "hphp/util/hash-set.h"
29 #include "hphp/util/struct-log.h"
30 #include "hphp/util/timer.h"
32 #include <boost/filesystem.hpp>
33 #include <folly/Range.h>
34 #include <folly/Format.h>
35 #include <folly/Memory.h>
37 namespace HPHP {
38 ///////////////////////////////////////////////////////////////////////////////
40 void WarmupRequestHandler::setupRequest(Transport* transport) {
41 m_reqHandler.setupRequest(transport);
44 void WarmupRequestHandler::teardownRequest(Transport* transport) noexcept {
45 m_reqHandler.teardownRequest(transport);
48 void WarmupRequestHandler::handleRequest(Transport *transport) {
49 // There is one WarmupRequestHandler per-thread, but we want to track request
50 // count across all threads. Therefore we let WarmupRequestHandlerFactory
51 // track the global request count.
52 m_factory->bumpReqCount();
53 m_reqHandler.handleRequest(transport);
56 void WarmupRequestHandler::abortRequest(Transport *transport) {
57 m_reqHandler.abortRequest(transport);
60 void WarmupRequestHandler::logToAccessLog(Transport *transport) {
61 m_reqHandler.logToAccessLog(transport);
64 std::unique_ptr<RequestHandler> WarmupRequestHandlerFactory::createHandler() {
65 return
66 std::make_unique<WarmupRequestHandler>(m_timeout, shared_from_this());
69 void WarmupRequestHandlerFactory::bumpReqCount() {
70 // Bump the request count. When we hit m_warmupReqThreshold,
71 // add additional threads to the server.
72 auto const oldReqNum = m_reqNumber.fetch_add(1, std::memory_order_relaxed);
73 if (oldReqNum != m_warmupReqThreshold) {
74 return;
77 Logger::Info("Finished warmup; saturating worker threads");
78 m_server->saturateWorkers();
81 void InternalWarmupWorker::doJob(WarmupJob job) {
82 if (f_server_is_stopping()) return;
83 if (f_server_uptime() > 0 &&
84 jit::mcgen::retranslateAllScheduled()) return;
85 HttpServer::CheckMemAndWait();
86 folly::StringPiece f(job.hdfFile);
87 auto const pos = f.rfind('/');
88 auto const str = (pos == f.npos) ? f : f.subpiece(pos + 1);
89 BootStats::Block timer(folly::sformat("warmup:{}:{}", str, job.index),
90 RuntimeOption::ServerExecutionMode());
91 try {
92 HttpRequestHandler handler(0);
93 ReplayTransport rt;
94 Logger::FInfo("Replaying warmup request {}:{}", job.hdfFile, job.index);
95 timespec start;
96 Timer::GetMonotonicTime(start);
97 rt.onRequestStart(start);
98 rt.replayInput(Hdf(job.hdfFile));
99 handler.run(&rt);
100 } catch (std::exception& e) {
101 Logger::FWarning("Got exception during warmup request {}:{}, {}",
102 job.hdfFile, job.index, e.what());
106 InternalWarmupRequestPlayer::InternalWarmupRequestPlayer(int threadCount,
107 bool dedup)
108 : JobQueueDispatcher<InternalWarmupWorker>(threadCount, threadCount,
109 0, false, nullptr)
110 , m_noDuplicate(dedup) {
113 InternalWarmupRequestPlayer::~InternalWarmupRequestPlayer() {
114 waitEmpty();
117 void InternalWarmupRequestPlayer::
118 runAfterDelay(const std::vector<std::string>& files,
119 unsigned nTimes, unsigned delaySeconds) {
120 if (nTimes == 0) return;
121 if (delaySeconds) {
122 /* sleep override */
123 sleep(delaySeconds);
125 start();
126 hphp_fast_string_map<unsigned> seen;
127 hphp_fast_string_set deduped;
128 do {
129 deduped.clear();
130 for (auto const& file : files) {
131 if (m_noDuplicate && !deduped.insert(file).second) continue;
132 try {
133 boost::filesystem::path p(file);
134 if (boost::filesystem::is_regular_file(p)) {
135 enqueue(WarmupJob{file, ++seen[file]});
136 } else if (boost::filesystem::is_directory(p)) {
137 for (auto const& f : boost::filesystem::directory_iterator(p)) {
138 if (boost::filesystem::is_regular_file(f.path())) {
139 std::string subFile = f.path().native();
140 // Only do it for .hdf files.
141 if (subFile.size() < 5 ||
142 subFile.substr(subFile.size() - 4) != ".hdf") {
143 Logger::FWarning("Skipping {} for warmup because it doesn't "
144 "look like a .hdf file", subFile);
145 continue;
147 enqueue(WarmupJob{subFile, ++seen[subFile]});
151 } catch (std::exception& e) {
152 Logger::FError("Exception preparing warmup requests: {}", e.what());
155 } while (--nTimes);
156 // Log what was replayed.
157 if (StructuredLog::enabled()) {
158 for (const auto& row : seen) {
159 StructuredLogEntry cols;
160 cols.setStr("file", row.first);
161 cols.setInt("times", row.second);
162 StructuredLog::log("hhvm_replay", cols);
167 ///////////////////////////////////////////////////////////////////////////////