Clingo
Loading...
Searching...
No Matches
profile.hh
1#pragma once
2
3#include <cassert>
4#include <cstddef>
5#include <functional>
6#include <memory>
7#include <numeric>
8#include <ostream>
9#include <sstream>
10#include <variant>
11#include <vector>
12
13namespace CppClingo::Ground {
14
17
19enum class ProfileType : uint8_t {
20 step,
21 accu
22};
23
25enum class ProfileDetail : uint8_t {
26 compact = 0,
27 detailed = 1,
28};
29
32 public:
34 explicit ProfileIndent(size_t level, size_t width = 2) : level{level}, width{width} {}
35
37 friend auto operator<<(std::ostream &out, ProfileIndent const &indent) -> std::ostream & {
38 for (size_t i = 0; i < indent.level * indent.width; ++i) {
39 out << ' ';
40 }
41 return out;
42 }
43
45 friend auto operator+(ProfileIndent const &indent, size_t add) -> ProfileIndent {
46 return ProfileIndent{indent.level + add, indent.width};
47 }
48
50 friend auto operator+=(ProfileIndent &indent, size_t add) -> ProfileIndent & {
51 indent.level += add;
52 return indent;
53 }
54
55 private:
57 size_t level;
59 size_t width;
60};
61
65 ProfileStats() = default;
66
69
74 void accumulate(ProfileStats const &stats, bool nested = false) {
75 matches += stats.matches;
76 instances += stats.instances;
77 if (!nested) {
80 }
81 }
82
84 void print(std::ostream &out, ProfileIndent indent) const;
85
87 [[nodiscard]] auto score() const -> double {
88 return static_cast<double>(time_instantiate) + static_cast<double>(time_propagate);
89 }
90
92 uint64_t matches = 0;
94 uint64_t instances = 0;
96 uint64_t time_instantiate = 0;
98 uint64_t time_propagate = 0;
99};
100
103 public:
105 using Visitor = std::function<void(
106 std::variant<std::pair<std::string_view, bool>, std::pair<ProfileStats const *, ProfileType>>, size_t)>;
107
109 ProfileNode() = default;
111 ProfileNode(ProfileNode const &other) = delete;
113 auto operator=(ProfileNode const &other) -> ProfileNode & = delete;
114
116 virtual ~ProfileNode() = default;
117
122 void print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const {
123 do_print(out, indent, detail, type);
124 }
125
127 [[nodiscard]] auto equal(ProfileNode const &node) const -> bool { return do_equal(node); }
128
130 [[nodiscard]] virtual auto score(ProfileType type) const -> double { return do_score(type); }
131
133 virtual void begin_step() { do_begin_step(); }
134
136 virtual void end_step() { do_end_step(); }
137
139 virtual void combine(ProfileStats &stats, ProfileType type, bool nested) const { do_combine(stats, type, nested); }
140
142 void accept(Visitor const &visit, size_t depth) const { do_accept(visit, depth); }
143
144 private:
145 virtual void do_print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const = 0;
146 [[nodiscard]] virtual auto do_equal(ProfileNode const &node) const -> bool = 0;
147 [[nodiscard]] virtual auto do_score(ProfileType type) const -> double = 0;
148 virtual void do_combine(ProfileStats &stats, ProfileType type, bool nested) const = 0;
149 virtual void do_begin_step() = 0;
150 virtual void do_end_step() = 0;
151 virtual void do_accept(Visitor const &visit, size_t depth) const = 0;
152};
153
156 public:
160 template <class T> auto add_child(std::unique_ptr<T> child) -> T & {
161 assert(child != nullptr);
162 auto *ret = child.get();
163 auto *ins = do_add_child(std::move(child));
164 assert(dynamic_cast<T *>(ins) != nullptr);
165 return ins != nullptr ? *static_cast<T *>(ins) : *ret;
166 }
167
168 private:
170 virtual auto do_add_child(std::unique_ptr<ProfileNode> child) -> ProfileNode * = 0;
171};
172
174template <typename T> class ProfileNodeExpression : public ProfileNodeInternal {
175 public:
177 ProfileNodeExpression(T expr, bool nested = false) : expr_{std::move(expr)}, nested_{nested} {}
178
179 private:
181 auto do_add_child(std::unique_ptr<ProfileNode> child) -> ProfileNode * override {
182 for (auto const &x : children_) {
183 if (x->equal(*child)) {
184 return x.get();
185 }
186 }
187 children_.emplace_back(std::move(child));
188 return children_.back().get();
189 }
190
192 void do_print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const override {
193 out << indent << (nested_ ? "[" : "") << expr_ << (nested_ ? "]" : "") << "\n";
194 if (detail == ProfileDetail::detailed) {
195 for (auto const &child : children_) {
196 child->print(out, indent + 1, detail, type);
197 }
198 } else {
199 auto stats = ProfileStats{};
200 combine(stats, type, false);
201 stats.print(out, indent + 1);
202 }
203 }
204
206 [[nodiscard]] auto do_equal(ProfileNode const &node) const -> bool override {
207 auto const *other = dynamic_cast<ProfileNodeExpression const *>(&node);
208 if constexpr (requires { expr_.get(); }) {
209 return other != nullptr && nested_ == other->nested_ && expr_.get() == other->expr_.get();
210 } else {
211 return other != nullptr && nested_ == other->nested_ && expr_ == other->expr_;
212 }
213 }
214
216 [[nodiscard]] auto do_score(ProfileType type) const -> double override {
217 return !nested_ ? std::accumulate(children_.begin(), children_.end(), 0.0,
218 [=](double sum, auto const &child) { return sum + child->score(type); })
219 : 0;
220 }
221
223 void do_begin_step() override {
224 for (auto &child : children_) {
225 child->begin_step();
226 }
227 }
228
230 void do_end_step() override {
231 for (auto &child : children_) {
232 child->end_step();
233 }
234 }
235
237 void do_combine(ProfileStats &stats, ProfileType type, bool nested) const override {
238 for (auto const &child : children_) {
239 child->combine(stats, type, nested || nested_);
240 }
241 }
242
244 void do_accept(Visitor const &visit, size_t depth) const override {
245 std::ostringstream oss;
246 oss << expr_;
247 visit(std::make_pair(oss.view(), nested_), depth);
248 for (auto const &child : children_) {
249 child->accept(visit, depth + 1);
250 }
251 }
252
254 T expr_;
256 std::vector<std::unique_ptr<ProfileNode>> children_;
258 bool nested_;
259};
260
262class ProfileData : public ProfileNode {
263 public:
265 ProfileData() = default;
266
267 private:
268 friend class Instantiator;
269
271 void do_print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const override {
272 std::ignore = detail;
273 type == ProfileType::step ? step_.print(out, indent) : accu_.print(out, indent);
274 }
276 [[nodiscard]] auto do_equal(ProfileNode const &node) const -> bool override {
277 auto const *other = dynamic_cast<ProfileData const *>(&node);
278 return other != nullptr;
279 }
281 [[nodiscard]] auto do_score(ProfileType type) const -> double override {
282 return type == ProfileType::step ? step_.score() : accu_.score();
283 }
285 void do_begin_step() override { step_.reset(); }
287 void do_end_step() override { accu_.accumulate(step_); }
289 void do_combine(ProfileStats &stats, ProfileType type, bool nested) const override {
290 if (type == ProfileType::step) {
291 stats.accumulate(step_, nested);
292 } else {
293 stats.accumulate(accu_, nested);
294 }
295 }
296
298 void do_accept(Visitor const &visit, size_t depth) const override {
299 visit(std::make_pair(&step_, ProfileType::step), depth);
300 visit(std::make_pair(&accu_, ProfileType::accu), depth);
301 }
302
304 ProfileStats step_;
306 ProfileStats accu_;
307};
308
310
311} // namespace CppClingo::Ground
An instantiator implementing the basic grounding algorithm.
Definition instantiator.hh:143
This profile node holds the profiling data for a single step and accumulated data.
Definition profile.hh:262
ProfileData()=default
Construct the profile data.
A profile node that holds a printable expression and children.
Definition profile.hh:174
ProfileNodeExpression(T expr, bool nested=false)
Construct the profile node with the given expression.
Definition profile.hh:177
Profile node that can hold children.
Definition profile.hh:155
auto add_child(std::unique_ptr< T > child) -> T &
Add a child profile node.
Definition profile.hh:160
Base class for profiling data.
Definition profile.hh:102
ProfileNode()=default
The default constructor.
void print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const
Print the profiling data to the given output stream.
Definition profile.hh:122
virtual auto score(ProfileType type) const -> double
Get a score for sorting profile nodes.
Definition profile.hh:130
std::function< void(std::variant< std::pair< std::string_view, bool >, std::pair< ProfileStats const *, ProfileType > >, size_t)> Visitor
The type of visitor function to use for visiting profile nodes.
Definition profile.hh:106
virtual void combine(ProfileStats &stats, ProfileType type, bool nested) const
Combine stats below this node.
Definition profile.hh:139
ProfileNode(ProfileNode const &other)=delete
Delete the copy constructor.
virtual ~ProfileNode()=default
Destructor.
void accept(Visitor const &visit, size_t depth) const
Visit the profile node with the given visitor function.
Definition profile.hh:142
virtual void end_step()
Accumulate the per step stats into the accumulated stats.
Definition profile.hh:136
virtual void begin_step()
Reset the per step statistics.
Definition profile.hh:133
auto equal(ProfileNode const &node) const -> bool
Compare this profile node with another for equality.
Definition profile.hh:127
auto operator=(ProfileNode const &other) -> ProfileNode &=delete
Delete assignment operator.
@ sum
The #count function.
void visit(Visitor const &fun, Node const &node)
Visit the given node with the visitor.
Definition ast.hh:665
ProfileType
Whether to process per step or accumulated profiling data.
Definition profile.hh:19
ProfileDetail
Whether to print profile data into a compact or detailed form.
Definition profile.hh:25
@ accu
Profile data accumulated over all steps.
@ step
Profile data for a single step.
Helper to print indentation.
Definition profile.hh:31
ProfileIndent(size_t level, size_t width=2)
Construct the indent with the given amount.
Definition profile.hh:34
friend auto operator+(ProfileIndent const &indent, size_t add) -> ProfileIndent
Add indentation to the given indent.
Definition profile.hh:45
friend auto operator<<(std::ostream &out, ProfileIndent const &indent) -> std::ostream &
Print the given indentation to the given output stream.
Definition profile.hh:37
friend auto operator+=(ProfileIndent &indent, size_t add) -> ProfileIndent &
Add indentation to the current indent (inplace).
Definition profile.hh:50
The profiling data.
Definition profile.hh:63
uint64_t time_instantiate
The time in nanoseconds spent instantiating.
Definition profile.hh:96
void print(std::ostream &out, ProfileIndent indent) const
Print the profiling data to the given output stream.
void accumulate(ProfileStats const &stats, bool nested=false)
Accumulate the given step stats into this stats object.
Definition profile.hh:74
uint64_t matches
The number of matches produced by the instantiator.
Definition profile.hh:92
void reset()
Reset the profiling data to zero.
Definition profile.hh:68
uint64_t instances
The number of instances produced by the instantiator.
Definition profile.hh:94
uint64_t time_propagate
The time in nanoseconds spent propagating.
Definition profile.hh:98
auto score() const -> double
Compute a score for sorting profile nodes based on time.
Definition profile.hh:87
ProfileStats()=default
The default constructor.