cmMakefileProfilingData: Refactor to use RAII

And add a more generic StartEntry() method.
This commit is contained in:
Kyle Edwards 2022-10-25 14:30:25 -04:00
parent fd57ced75a
commit 3d6a8d7eac
4 changed files with 97 additions and 21 deletions

View File

@ -375,19 +375,15 @@ public:
++this->Makefile->RecursionDepth;
this->Makefile->ExecutionStatusStack.push_back(&status);
#if !defined(CMAKE_BOOTSTRAP)
if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) {
this->Makefile->GetCMakeInstance()->GetProfilingOutput().StartEntry(lff,
lfc);
}
this->ProfilingDataRAII =
this->Makefile->GetCMakeInstance()->CreateProfilingEntry(lff, lfc);
#endif
}
~cmMakefileCall()
{
#if !defined(CMAKE_BOOTSTRAP)
if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) {
this->Makefile->GetCMakeInstance()->GetProfilingOutput().StopEntry();
}
this->ProfilingDataRAII.reset();
#endif
this->Makefile->ExecutionStatusStack.pop_back();
--this->Makefile->RecursionDepth;
@ -399,6 +395,9 @@ public:
private:
cmMakefile* Makefile;
#if !defined(CMAKE_BOOTSTRAP)
cm::optional<cmMakefileProfilingData::RAII> ProfilingDataRAII;
#endif
};
void cmMakefile::OnExecuteCommand(std::function<void()> callback)

View File

@ -4,8 +4,12 @@
#include <chrono>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include <vector>
#include <cm/utility>
#include <cm3p/json/value.h>
#include <cm3p/json/writer.h>
@ -45,6 +49,23 @@ cmMakefileProfilingData::~cmMakefileProfilingData() noexcept
void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff,
cmListFileContext const& lfc)
{
cm::optional<Json::Value> argsValue(cm::in_place, Json::objectValue);
if (!lff.Arguments().empty()) {
std::string args;
for (auto const& a : lff.Arguments()) {
args = cmStrCat(args, args.empty() ? "" : " ", a.Value);
}
(*argsValue)["functionArgs"] = args;
}
(*argsValue)["location"] =
cmStrCat(lfc.FilePath, ':', std::to_string(lfc.Line));
this->StartEntry("cmake", lff.LowerCaseName(), std::move(argsValue));
}
void cmMakefileProfilingData::StartEntry(const std::string& category,
const std::string& name,
cm::optional<Json::Value> args)
{
/* Do not try again if we previously failed to write to output. */
if (!this->ProfileStream.good()) {
@ -58,24 +79,17 @@ void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff,
cmsys::SystemInformation info;
Json::Value v;
v["ph"] = "B";
v["name"] = lff.LowerCaseName();
v["cat"] = "cmake";
v["name"] = name;
v["cat"] = category;
v["ts"] = static_cast<Json::Value::UInt64>(
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count());
v["pid"] = static_cast<int>(info.GetProcessId());
v["tid"] = 0;
Json::Value argsValue;
if (!lff.Arguments().empty()) {
std::string args;
for (auto const& a : lff.Arguments()) {
args += (args.empty() ? "" : " ") + a.Value;
}
argsValue["functionArgs"] = args;
if (args) {
v["args"] = *std::move(args);
}
argsValue["location"] = lfc.FilePath + ":" + std::to_string(lfc.Line);
v["args"] = argsValue;
this->JsonWriter->write(v, &this->ProfileStream);
} catch (std::ios_base::failure& fail) {
@ -112,3 +126,27 @@ void cmMakefileProfilingData::StopEntry()
cmSystemTools::Error("Error writing profiling output!");
}
}
cmMakefileProfilingData::RAII::RAII(RAII&& other) noexcept
: Data(other.Data)
{
other.Data = nullptr;
}
cmMakefileProfilingData::RAII::~RAII()
{
if (this->Data) {
this->Data->StopEntry();
}
}
cmMakefileProfilingData::RAII& cmMakefileProfilingData::RAII::operator=(
RAII&& other) noexcept
{
if (this->Data) {
this->Data->StopEntry();
}
this->Data = other.Data;
other.Data = nullptr;
return *this;
}

View File

@ -3,6 +3,11 @@
#pragma once
#include <memory>
#include <string>
#include <utility>
#include <cm/optional>
#include <cm3p/json/value.h> // IWYU pragma: keep
#include "cmsys/FStream.hxx"
@ -19,8 +24,33 @@ public:
cmMakefileProfilingData(const std::string&);
~cmMakefileProfilingData() noexcept;
void StartEntry(const cmListFileFunction& lff, cmListFileContext const& lfc);
void StartEntry(const std::string& category, const std::string& name,
cm::optional<Json::Value> args = cm::nullopt);
void StopEntry();
class RAII
{
public:
RAII() = delete;
RAII(const RAII&) = delete;
RAII(RAII&&) noexcept;
template <typename... Args>
RAII(cmMakefileProfilingData& data, Args&&... args)
: Data(&data)
{
this->Data->StartEntry(std::forward<Args>(args)...);
}
~RAII();
RAII& operator=(const RAII&) = delete;
RAII& operator=(RAII&&) noexcept;
private:
cmMakefileProfilingData* Data = nullptr;
};
private:
cmsys::ofstream ProfileStream;
std::unique_ptr<Json::StreamWriter> JsonWriter;

View File

@ -33,6 +33,7 @@
# include <cm3p/json/value.h>
# include "cmCMakePresetsGraph.h"
# include "cmMakefileProfilingData.h"
#endif
class cmExternalMakefileProjectGeneratorFactory;
@ -41,9 +42,6 @@ class cmFileTimeCache;
class cmGlobalGenerator;
class cmGlobalGeneratorFactory;
class cmMakefile;
#if !defined(CMAKE_BOOTSTRAP)
class cmMakefileProfilingData;
#endif
class cmMessenger;
class cmVariableWatch;
struct cmBuildOptions;
@ -628,6 +626,17 @@ public:
#if !defined(CMAKE_BOOTSTRAP)
cmMakefileProfilingData& GetProfilingOutput();
bool IsProfilingEnabled() const;
template <typename... Args>
cm::optional<cmMakefileProfilingData::RAII> CreateProfilingEntry(
Args&&... args)
{
if (this->IsProfilingEnabled()) {
return cm::make_optional<cmMakefileProfilingData::RAII>(
this->GetProfilingOutput(), std::forward<Args>(args)...);
}
return cm::nullopt;
}
#endif
protected: