/src/CMake/Source/cmMakefileProfilingData.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmMakefileProfilingData.h" |
4 | | |
5 | | #include <chrono> |
6 | | #include <stdexcept> |
7 | | #include <utility> |
8 | | |
9 | | #include <cm3p/json/value.h> |
10 | | #include <cm3p/json/writer.h> |
11 | | |
12 | | #include "cmsys/FStream.hxx" |
13 | | #include "cmsys/SystemInformation.hxx" |
14 | | |
15 | | #include "cmStringAlgorithms.h" |
16 | | #include "cmSystemTools.h" |
17 | | |
18 | | cmMakefileProfilingData::cmMakefileProfilingData( |
19 | | std::string const& profileStream) |
20 | 0 | { |
21 | 0 | std::ios::openmode omode = std::ios::out | std::ios::trunc; |
22 | 0 | this->ProfileStream.open(profileStream.c_str(), omode); |
23 | 0 | Json::StreamWriterBuilder wbuilder; |
24 | 0 | this->JsonWriter = |
25 | 0 | std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter()); |
26 | 0 | if (!this->ProfileStream.good()) { |
27 | 0 | throw std::runtime_error(std::string("Unable to open: ") + profileStream); |
28 | 0 | } |
29 | | |
30 | 0 | this->ProfileStream << "["; |
31 | 0 | } |
32 | | |
33 | | cmMakefileProfilingData::~cmMakefileProfilingData() noexcept |
34 | 0 | { |
35 | 0 | if (this->ProfileStream.good()) { |
36 | 0 | try { |
37 | 0 | this->ProfileStream << "]"; |
38 | 0 | this->ProfileStream.close(); |
39 | 0 | } catch (...) { |
40 | 0 | cmSystemTools::Error("Error writing profiling output!"); |
41 | 0 | } |
42 | 0 | } |
43 | 0 | } |
44 | | |
45 | | void cmMakefileProfilingData::StartEntry(std::string const& category, |
46 | | std::string const& name, |
47 | | cm::optional<Json::Value> args) |
48 | 0 | { |
49 | | /* Do not try again if we previously failed to write to output. */ |
50 | 0 | if (!this->ProfileStream.good()) { |
51 | 0 | return; |
52 | 0 | } |
53 | | |
54 | 0 | try { |
55 | 0 | if (this->ProfileStream.tellp() > 1) { |
56 | 0 | this->ProfileStream << ","; |
57 | 0 | } |
58 | 0 | cmsys::SystemInformation info; |
59 | 0 | Json::Value v; |
60 | 0 | v["ph"] = "B"; |
61 | 0 | v["name"] = name; |
62 | 0 | v["cat"] = category; |
63 | 0 | v["ts"] = static_cast<Json::Value::UInt64>( |
64 | 0 | std::chrono::duration_cast<std::chrono::microseconds>( |
65 | 0 | std::chrono::steady_clock::now().time_since_epoch()) |
66 | 0 | .count()); |
67 | 0 | v["pid"] = static_cast<int>(info.GetProcessId()); |
68 | 0 | v["tid"] = 0; |
69 | 0 | if (args) { |
70 | 0 | v["args"] = *std::move(args); |
71 | 0 | } |
72 | |
|
73 | 0 | this->JsonWriter->write(v, &this->ProfileStream); |
74 | 0 | } catch (std::ios_base::failure& fail) { |
75 | 0 | cmSystemTools::Error( |
76 | 0 | cmStrCat("Failed to write to profiling output: ", fail.what())); |
77 | 0 | } catch (...) { |
78 | 0 | cmSystemTools::Error("Error writing profiling output!"); |
79 | 0 | } |
80 | 0 | } |
81 | | |
82 | | void cmMakefileProfilingData::StopEntry() |
83 | 0 | { |
84 | | /* Do not try again if we previously failed to write to output. */ |
85 | 0 | if (!this->ProfileStream.good()) { |
86 | 0 | return; |
87 | 0 | } |
88 | | |
89 | 0 | try { |
90 | 0 | this->ProfileStream << ","; |
91 | 0 | cmsys::SystemInformation info; |
92 | 0 | Json::Value v; |
93 | 0 | v["ph"] = "E"; |
94 | 0 | v["ts"] = static_cast<Json::Value::UInt64>( |
95 | 0 | std::chrono::duration_cast<std::chrono::microseconds>( |
96 | 0 | std::chrono::steady_clock::now().time_since_epoch()) |
97 | 0 | .count()); |
98 | 0 | v["pid"] = static_cast<int>(info.GetProcessId()); |
99 | 0 | v["tid"] = 0; |
100 | 0 | this->JsonWriter->write(v, &this->ProfileStream); |
101 | 0 | } catch (std::ios_base::failure& fail) { |
102 | 0 | cmSystemTools::Error( |
103 | 0 | cmStrCat("Failed to write to profiling output:", fail.what())); |
104 | 0 | } catch (...) { |
105 | 0 | cmSystemTools::Error("Error writing profiling output!"); |
106 | 0 | } |
107 | 0 | } |
108 | | |
109 | | cmMakefileProfilingData::RAII::RAII(cmMakefileProfilingData& data, |
110 | | std::string const& category, |
111 | | std::string const& name, |
112 | | cm::optional<Json::Value> args) |
113 | 0 | : Data(&data) |
114 | 0 | { |
115 | 0 | this->Data->StartEntry(category, name, std::move(args)); |
116 | 0 | } |
117 | | |
118 | | cmMakefileProfilingData::RAII::RAII(RAII&& other) noexcept |
119 | 0 | : Data(other.Data) |
120 | 0 | { |
121 | 0 | other.Data = nullptr; |
122 | 0 | } |
123 | | |
124 | | cmMakefileProfilingData::RAII::~RAII() |
125 | 0 | { |
126 | 0 | if (this->Data) { |
127 | 0 | this->Data->StopEntry(); |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | | cmMakefileProfilingData::RAII& cmMakefileProfilingData::RAII::operator=( |
132 | | RAII&& other) noexcept |
133 | 0 | { |
134 | 0 | if (this->Data) { |
135 | 0 | this->Data->StopEntry(); |
136 | 0 | } |
137 | 0 | this->Data = other.Data; |
138 | 0 | other.Data = nullptr; |
139 | 0 | return *this; |
140 | 0 | } |