Skip to content

Commit ba08eb4

Browse files
gdankelfacebook-github-bot
authored andcommitted
Invert ConfigLoader -> profiler dependency (take 2) (#271)
Summary: Pull Request resolved: #271 Change direction of dependency from ConfigLoader -> profiler to profiler -> ConfigLoader. This way, the profiler is able to lazily initialize config loader and also move towards the pluggable profiler design. Differential Revision: D28976077 fbshipit-source-id: 9a46bf5ab78d2d3abb4ed3e99686beadeea90edc
1 parent 34f66a6 commit ba08eb4

16 files changed

+230
-137
lines changed

libkineto/include/libkineto.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ extern "C" {
3636
namespace libkineto {
3737

3838
class Config;
39+
class ConfigLoader;
3940

4041
struct CpuTraceBuffer {
4142
TraceSpan span{0, 0, "none"};
@@ -46,6 +47,9 @@ struct CpuTraceBuffer {
4647
class LibkinetoApi {
4748
public:
4849

50+
LibkinetoApi(ConfigLoader& configLoader) : configLoader_(configLoader) {
51+
}
52+
4953
// Called by client that supports tracing API.
5054
// libkineto can still function without this.
5155
void registerClient(ClientInterface* client);
@@ -92,11 +96,17 @@ class LibkinetoApi {
9296
suppressLibkinetoLogMessages();
9397
}
9498

99+
// Provides access to profier configuration manaegement
100+
ConfigLoader& configLoader() {
101+
return configLoader_;
102+
}
103+
95104
private:
96105

97106
// Client is initialized once both it and libkineto has registered
98107
void initClientIfRegistered();
99108

109+
ConfigLoader& configLoader_;
100110
std::unique_ptr<ActivityProfilerInterface> activityProfiler_{};
101111
ClientInterface* client_{};
102112
int32_t clientRegisterThread_{0};

libkineto/src/ActivityProfilerController.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,18 @@ namespace KINETO_NAMESPACE {
2525

2626
constexpr milliseconds kProfilerIntervalMsecs(1000);
2727

28-
ActivityProfilerController::ActivityProfilerController(bool cpuOnly) {
29-
profiler_ = std::make_unique<ActivityProfiler>(CuptiActivityInterface::singleton(), cpuOnly);
28+
ActivityProfilerController::ActivityProfilerController(
29+
ConfigLoader& configLoader, bool cpuOnly)
30+
: configLoader_(configLoader) {
31+
profiler_ = std::make_unique<ActivityProfiler>(
32+
CuptiActivityInterface::singleton(), cpuOnly);
33+
configLoader_.addHandler(ConfigLoader::ConfigKind::ActivityProfiler, this);
3034
}
3135

3236
ActivityProfilerController::~ActivityProfilerController() {
37+
LOG(INFO) << "ActivityProfilerController::~ActivityProfilerController()";
38+
configLoader_.removeHandler(
39+
ConfigLoader::ConfigKind::ActivityProfiler, this);
3340
if (profilerThread_) {
3441
// signaling termination of the profiler loop
3542
stopRunloop_ = true;
@@ -65,6 +72,17 @@ static std::unique_ptr<ActivityLogger> makeLogger(const Config& config) {
6572
return loggerFactory().makeLogger(config.activitiesLogUrl());
6673
}
6774

75+
bool ActivityProfilerController::canAcceptConfig() {
76+
return !profiler_->isActive();
77+
}
78+
79+
void ActivityProfilerController::acceptConfig(const Config& config) {
80+
VLOG(1) << "acceptConfig";
81+
if (config.activityProfilerEnabled()) {
82+
scheduleTrace(config);
83+
}
84+
}
85+
6886
void ActivityProfilerController::profilerLoop() {
6987
setThreadName("Kineto Activity Profiler");
7088
VLOG(0) << "Entering activity profiler loop";
@@ -107,6 +125,11 @@ void ActivityProfilerController::profilerLoop() {
107125
}
108126

109127
void ActivityProfilerController::scheduleTrace(const Config& config) {
128+
VLOG(1) << "scheduleTrace";
129+
if (profiler_->isActive()) {
130+
LOG(ERROR) << "Ignored request - profiler busy";
131+
return;
132+
}
110133
std::lock_guard<std::mutex> lock(asyncConfigLock_);
111134
asyncRequestConfig_ = config.clone();
112135
// start a profilerLoop() thread to handle request

libkineto/src/ActivityProfilerController.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,23 @@
99

1010
#include <atomic>
1111
#include <memory>
12+
#include <mutex>
1213
#include <thread>
1314

1415
#include "ActivityLoggerFactory.h"
1516
#include "ActivityProfiler.h"
1617
#include "ActivityProfilerInterface.h"
1718
#include "ActivityTraceInterface.h"
19+
#include "ConfigLoader.h"
1820
#include "CuptiActivityInterface.h"
1921

2022
namespace KINETO_NAMESPACE {
2123

2224
class Config;
2325

24-
class ActivityProfilerController {
26+
class ActivityProfilerController : public ConfigLoader::ConfigHandler {
2527
public:
26-
explicit ActivityProfilerController(bool cpuOnly);
28+
explicit ActivityProfilerController(ConfigLoader& configLoader, bool cpuOnly);
2729
ActivityProfilerController(const ActivityProfilerController&) = delete;
2830
ActivityProfilerController& operator=(const ActivityProfilerController&) =
2931
delete;
@@ -34,6 +36,9 @@ class ActivityProfilerController {
3436
const std::string& protocol,
3537
ActivityLoggerFactory::FactoryFunc factory);
3638

39+
bool canAcceptConfig() override;
40+
void acceptConfig(const Config& config) override;
41+
3742
void scheduleTrace(const Config& config);
3843

3944
void prepareTrace(const Config& config);
@@ -72,6 +77,7 @@ class ActivityProfilerController {
7277
std::unique_ptr<ActivityLogger> logger_;
7378
std::thread* profilerThread_{nullptr};
7479
std::atomic_bool stopRunloop_{false};
80+
ConfigLoader& configLoader_;
7581
};
7682

7783
} // namespace KINETO_NAMESPACE

libkineto/src/ActivityProfilerProxy.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,21 @@
1313

1414
namespace KINETO_NAMESPACE {
1515

16-
void ActivityProfilerProxy::init() {
17-
if (!controller_) {
18-
controller_ = new ActivityProfilerController(cpuOnly_);
19-
}
16+
ActivityProfilerProxy::ActivityProfilerProxy(
17+
bool cpuOnly, ConfigLoader& configLoader)
18+
: cpuOnly_(cpuOnly), configLoader_(configLoader) {
2019
}
2120

2221
ActivityProfilerProxy::~ActivityProfilerProxy() {
2322
delete controller_;
2423
};
2524

25+
void ActivityProfilerProxy::init() {
26+
if (!controller_) {
27+
controller_ = new ActivityProfilerController(configLoader_, cpuOnly_);
28+
}
29+
}
30+
2631
void ActivityProfilerProxy::scheduleTrace(const std::string& configStr) {
2732
Config config;
2833
config.parse(configStr);

libkineto/src/ActivityProfilerProxy.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ using namespace libkineto;
2626

2727
class ActivityProfilerController;
2828
class Config;
29+
class ConfigLoader;
2930

3031
class ActivityProfilerProxy : public ActivityProfilerInterface {
3132

3233
public:
33-
ActivityProfilerProxy(bool cpuOnly) : cpuOnly_(cpuOnly) {}
34+
ActivityProfilerProxy(bool cpuOnly, ConfigLoader& configLoader);
3435
~ActivityProfilerProxy() override;
3536

3637
void init() override;
@@ -64,6 +65,7 @@ class ActivityProfilerProxy : public ActivityProfilerInterface {
6465

6566
private:
6667
bool cpuOnly_{true};
68+
ConfigLoader& configLoader_;
6769
ActivityProfilerController* controller_{nullptr};
6870
};
6971

libkineto/src/Config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ Config::Config()
148148
kDefaultActivitiesExternalAPINetSizeThreshold),
149149
activitiesExternalAPIGpuOpCountThreshold_(
150150
kDefaultActivitiesExternalAPIGpuOpCountThreshold),
151+
activitiesOnDemandTimestamp_(milliseconds(0)),
151152
requestTimestamp_(milliseconds(0)),
152153
enableSigUsr2_(true),
153154
enableIpcFabric_(false) {

libkineto/src/Config.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class Config : public AbstractConfig {
4545
}
4646

4747
bool activityProfilerEnabled() const {
48-
return activityProfilerEnabled_;
48+
return activityProfilerEnabled_ ||
49+
activitiesOnDemandTimestamp_.time_since_epoch().count() > 0;
4950
}
5051

5152
// Log activitiy trace to this file

libkineto/src/ConfigLoader.cpp

Lines changed: 23 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
#include <chrono>
1616
#include <fstream>
1717

18-
#include "libkineto.h"
19-
#include "ActivityProfilerProxy.h"
2018
#include "DaemonConfigLoader.h"
2119

2220
#include "Logger.h"
@@ -120,7 +118,7 @@ void ConfigLoader::setDaemonConfigLoaderFactory(
120118
}
121119

122120
ConfigLoader& ConfigLoader::instance() {
123-
static ConfigLoader config_loader(libkineto::api());
121+
static ConfigLoader config_loader;
124122
return config_loader;
125123
}
126124

@@ -130,9 +128,8 @@ std::string ConfigLoader::readOnDemandConfigFromDaemon(
130128
if (!daemonConfigLoader_) {
131129
return "";
132130
}
133-
bool events =
134-
now > onDemandEventProfilerConfig_->eventProfilerOnDemandEndTime();
135-
bool activities = !libkinetoApi_.activityProfiler().isActive();
131+
bool events = canHandlerAcceptConfig(ConfigKind::EventProfiler);
132+
bool activities = canHandlerAcceptConfig(ConfigKind::ActivityProfiler);
136133
return daemonConfigLoader_->readOnDemandConfig(events, activities);
137134
}
138135

@@ -144,10 +141,8 @@ int ConfigLoader::contextCountForGpu(uint32_t device) {
144141
return daemonConfigLoader_->gpuContextCount(device);
145142
}
146143

147-
ConfigLoader::ConfigLoader(LibkinetoApi& api)
148-
: libkinetoApi_(api),
149-
onDemandEventProfilerConfig_(new Config()),
150-
configUpdateIntervalSecs_(kConfigUpdateIntervalSecs),
144+
ConfigLoader::ConfigLoader()
145+
: configUpdateIntervalSecs_(kConfigUpdateIntervalSecs),
151146
onDemandConfigUpdateIntervalSecs_(kOnDemandConfigUpdateIntervalSecs),
152147
stopFlag_(false),
153148
onDemandSignal_(false) {
@@ -158,15 +153,21 @@ ConfigLoader::ConfigLoader(LibkinetoApi& api)
158153
config_.parse(readConfigFromConfigFile(configFileName_));
159154
SET_LOG_VERBOSITY_LEVEL(config_.verboseLogLevel(), config_.verboseLogModules());
160155
setupSignalHandler(config_.sigUsr2Enabled());
161-
if (daemonConfigLoaderFactory()) {
162-
daemonConfigLoader_ = daemonConfigLoaderFactory()();
163-
daemonConfigLoader_->setCommunicationFabric(config_.ipcFabricEnabled());
156+
}
157+
158+
void ConfigLoader::startThread() {
159+
if (!updateThread_) {
160+
if (daemonConfigLoaderFactory()) {
161+
daemonConfigLoader_ = daemonConfigLoaderFactory()();
162+
daemonConfigLoader_->setCommunicationFabric(config_.ipcFabricEnabled());
163+
}
164+
updateThread_ =
165+
std::make_unique<std::thread>(&ConfigLoader::updateConfigThread, this);
164166
}
165-
updateThread_ =
166-
std::make_unique<std::thread>(&ConfigLoader::updateConfigThread, this);
167167
}
168168

169169
ConfigLoader::~ConfigLoader() {
170+
LOG(INFO) << "ConfigLoader::~ConfigLoader()";
170171
if (updateThread_) {
171172
stopFlag_ = true;
172173
{
@@ -211,51 +212,23 @@ void ConfigLoader::configureFromSignal(
211212
if (daemonConfigLoader_) {
212213
daemonConfigLoader_->setCommunicationFabric(config_.ipcFabricEnabled());
213214
}
214-
if (eventProfilerRequest(config)) {
215-
if (now > onDemandEventProfilerConfig_->eventProfilerOnDemandEndTime()) {
216-
LOG(INFO) << "Starting on-demand event profiling from signal";
217-
std::lock_guard<std::mutex> lock(configLock_);
218-
onDemandEventProfilerConfig_ = config.clone();
219-
} else {
220-
LOG(ERROR) << "On-demand event profiler is busy";
221-
}
222-
}
223-
// Initiate a trace by default, even when not specified in the config.
224-
// Set trace duration and iterations to 0 to suppress.
225-
config.updateActivityProfilerRequestReceivedTime();
226-
try {
227-
auto& profiler = dynamic_cast<ActivityProfilerProxy&>(
228-
libkinetoApi_.activityProfiler());
229-
profiler.scheduleTrace(config);
230-
} catch (const std::exception& e) {
231-
LOG(ERROR) << "Failed to schedule profiler request (busy?)";
232-
}
215+
notifyHandlers(config);
233216
}
234217

235218
void ConfigLoader::configureFromDaemon(
236219
time_point<system_clock> now,
237220
Config& config) {
238221
const std::string config_str = readOnDemandConfigFromDaemon(now);
239-
LOG_IF(INFO, !config_str.empty()) << "Received config from dyno:\n"
240-
<< config_str;
222+
if (config_str.empty()) {
223+
return;
224+
}
225+
226+
LOG(INFO) << "Received config from dyno:\n" << config_str;
241227
config.parse(config_str);
242228
if (daemonConfigLoader_) {
243229
daemonConfigLoader_->setCommunicationFabric(config_.ipcFabricEnabled());
244230
}
245-
if (eventProfilerRequest(config)) {
246-
std::lock_guard<std::mutex> lock(configLock_);
247-
onDemandEventProfilerConfig_ = config.clone();
248-
}
249-
if (config_.activityProfilerEnabled() &&
250-
config.activityProfilerRequestReceivedTime() > now) {
251-
try {
252-
auto& profiler = dynamic_cast<ActivityProfilerProxy&>(
253-
libkinetoApi_.activityProfiler());
254-
profiler.scheduleTrace(config);
255-
} catch (const std::exception& e) {
256-
LOG(ERROR) << "Failed to schedule profiler request (busy?)";
257-
}
258-
}
231+
notifyHandlers(config);
259232
}
260233

261234
void ConfigLoader::updateConfigThread() {
@@ -313,10 +286,4 @@ bool ConfigLoader::hasNewConfig(const Config& oldConfig) {
313286
return config_.timestamp() > oldConfig.timestamp();
314287
}
315288

316-
bool ConfigLoader::hasNewEventProfilerOnDemandConfig(const Config& oldConfig) {
317-
std::lock_guard<std::mutex> lock(configLock_);
318-
return onDemandEventProfilerConfig_->eventProfilerOnDemandStartTime() >
319-
oldConfig.eventProfilerOnDemandStartTime();
320-
}
321-
322289
} // namespace KINETO_NAMESPACE

0 commit comments

Comments
 (0)