Clingo
Loading...
Searching...
No Matches
profile.hh
1#pragma once
2
3#include <cassert>
4#include <cstddef>
5#include <cstdint>
6#include <functional>
7#include <memory>
8#include <numeric>
9#include <ostream>
10#include <sstream>
11#include <variant>
12#include <vector>
13
14namespace CppClingo::Ground {
15
18
20enum class ProfileType : uint8_t {
21 step,
22 accu
23};
24
26enum class ProfileDetail : uint8_t {
27 compact = 0,
28 detailed = 1,
29};
30
33 public:
35 explicit ProfileIndent(size_t level, size_t width = 2) : level{level}, width{width} {}
36
38 friend auto operator<<(std::ostream &out, ProfileIndent const &indent) -> std::ostream & {
39 for (size_t i = 0; i < indent.level * indent.width; ++i) {
40 out << ' ';
41 }
42 return out;
43 }
44
46 friend auto operator+(ProfileIndent const &indent, size_t add) -> ProfileIndent {
47 return ProfileIndent{indent.level + add, indent.width};
48 }
49
51 friend auto operator+=(ProfileIndent &indent, size_t add) -> ProfileIndent & {
52 indent.level += add;
53 return indent;
54 }
55
56 private:
58 size_t level;
60 size_t width;
61};
62
66 ProfileStats() = default;
67
70
75 void accumulate(ProfileStats const &stats, bool nested = false) {
76 matches += stats.matches;
77 instances += stats.instances;
78 if (!nested) {
81 }
82 }
83
85 void print(std::ostream &out, ProfileIndent indent) const;
86
88 [[nodiscard]] auto score() const -> double {
89 return static_cast<double>(time_instantiate) + static_cast<double>(time_propagate);
90 }
91
93 uint64_t matches = 0;
95 uint64_t instances = 0;
97 uint64_t time_instantiate = 0;
99 uint64_t time_propagate = 0;
100};
101
104 public:
106 using Visitor = std::function<void(
107 std::variant<std::pair<std::string_view, bool>, std::pair<ProfileStats const *, ProfileType>>, size_t)>;
108
110 ProfileNode() = default;
112 ProfileNode(ProfileNode const &other) = delete;
114 auto operator=(ProfileNode const &other) -> ProfileNode & = delete;
115
117 virtual ~ProfileNode() = default;
118
123 void print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const {
124 do_print(out, indent, detail, type);
125 }
126
128 [[nodiscard]] auto equal(ProfileNode const &node) const -> bool { return do_equal(node); }
129
131 [[nodiscard]] virtual auto score(ProfileType type) const -> double { return do_score(type); }
132
134 virtual void begin_step() { do_begin_step(); }
135
137 virtual void end_step() { do_end_step(); }
138
140 virtual void combine(ProfileStats &stats, ProfileType type, bool nested) const { do_combine(stats, type, nested); }
141
143 void accept(Visitor const &visit, size_t depth) const { do_accept(visit, depth); }
144
145 private:
146 virtual void do_print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const = 0;
147 [[nodiscard]] virtual auto do_equal(ProfileNode const &node) const -> bool = 0;
148 [[nodiscard]] virtual auto do_score(ProfileType type) const -> double = 0;
149 virtual void do_combine(ProfileStats &stats, ProfileType type, bool nested) const = 0;
150 virtual void do_begin_step() = 0;
151 virtual void do_end_step() = 0;
152 virtual void do_accept(Visitor const &visit, size_t depth) const = 0;
153};
154
157 public:
161 template <class T> auto add_child(std::unique_ptr<T> child) -> T & {
162 assert(child != nullptr);
163 auto *ret = child.get();
164 auto *ins = do_add_child(std::move(child));
165 assert(dynamic_cast<T *>(ins) != nullptr);
166 return ins != nullptr ? *static_cast<T *>(ins) : *ret;
167 }
168
169 private:
171 virtual auto do_add_child(std::unique_ptr<ProfileNode> child) -> ProfileNode * = 0;
172};
173
175template <typename T> class ProfileNodeExpression : public ProfileNodeInternal {
176 public:
178 ProfileNodeExpression(T expr, bool nested = false) : expr_{std::move(expr)}, nested_{nested} {}
179
180 private:
182 auto do_add_child(std::unique_ptr<ProfileNode> child) -> ProfileNode * override {
183 for (auto const &x : children_) {
184 if (x->equal(*child)) {
185 return x.get();
186 }
187 }
188 children_.emplace_back(std::move(child));
189 return children_.back().get();
190 }
191
193 void do_print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const override {
194 out << indent << (nested_ ? "[" : "") << expr_ << (nested_ ? "]" : "") << "\n";
195 if (detail == ProfileDetail::detailed) {
196 for (auto const &child : children_) {
197 child->print(out, indent + 1, detail, type);
198 }
199 } else {
200 auto stats = ProfileStats{};
201 combine(stats, type, false);
202 stats.print(out, indent + 1);
203 }
204 }
205
207 [[nodiscard]] auto do_equal(ProfileNode const &node) const -> bool override {
208 auto const *other = dynamic_cast<ProfileNodeExpression const *>(&node);
209 if constexpr (requires { expr_.get(); }) {
210 return other != nullptr && nested_ == other->nested_ && expr_.get() == other->expr_.get();
211 } else {
212 return other != nullptr && nested_ == other->nested_ && expr_ == other->expr_;
213 }
214 }
215
217 [[nodiscard]] auto do_score(ProfileType type) const -> double override {
218 return !nested_ ? std::accumulate(children_.begin(), children_.end(), 0.0,
219 [=](double sum, auto const &child) { return sum + child->score(type); })
220 : 0;
221 }
222
224 void do_begin_step() override {
225 for (auto &child : children_) {
226 child->begin_step();
227 }
228 }
229
231 void do_end_step() override {
232 for (auto &child : children_) {
233 child->end_step();
234 }
235 }
236
238 void do_combine(ProfileStats &stats, ProfileType type, bool nested) const override {
239 for (auto const &child : children_) {
240 child->combine(stats, type, nested || nested_);
241 }
242 }
243
245 void do_accept(Visitor const &visit, size_t depth) const override {
246 std::ostringstream oss;
247 oss << expr_;
248 visit(std::make_pair(oss.view(), nested_), depth);
249 for (auto const &child : children_) {
250 child->accept(visit, depth + 1);
251 }
252 }
253
255 T expr_;
257 std::vector<std::unique_ptr<ProfileNode>> children_;
259 bool nested_;
260};
261
263class ProfileData : public ProfileNode {
264 public:
266 ProfileData() = default;
267
268 private:
269 friend class Instantiator;
270
272 void do_print(std::ostream &out, ProfileIndent indent, ProfileDetail detail, ProfileType type) const override {
273 std::ignore = detail;
274 type == ProfileType::step ? step_.print(out, indent) : accu_.print(out, indent);
275 }
277 [[nodiscard]] auto do_equal(ProfileNode const &node) const -> bool override {
278 auto const *other = dynamic_cast<ProfileData const *>(&node);
279 return other != nullptr;
280 }
282 [[nodiscard]] auto do_score(ProfileType type) const -> double override {
283 return type == ProfileType::step ? step_.score() : accu_.score();
284 }
286 void do_begin_step() override { step_.reset(); }
288 void do_end_step() override { accu_.accumulate(step_); }
290 void do_combine(ProfileStats &stats, ProfileType type, bool nested) const override {
291 if (type == ProfileType::step) {
292 stats.accumulate(step_, nested);
293 } else {
294 stats.accumulate(accu_, nested);
295 }
296 }
297
299 void do_accept(Visitor const &visit, size_t depth) const override {
300 visit(std::make_pair(&step_, ProfileType::step), depth);
301 visit(std::make_pair(&accu_, ProfileType::accu), depth);
302 }
303
305 ProfileStats step_;
307 ProfileStats accu_;
308};
309
311
312} // namespace CppClingo::Ground
An instantiator implementing the basic grounding algorithm.
Definition instantiator.hh:145
This profile node holds the profiling data for a single step and accumulated data.
Definition profile.hh:263
ProfileData()=default
Construct the profile data.
A profile node that holds a printable expression and children.
Definition profile.hh:175
ProfileNodeExpression(T expr, bool nested=false)
Construct the profile node with the given expression.
Definition profile.hh:178
Profile node that can hold children.
Definition profile.hh:156
auto add_child(std::unique_ptr< T > child) -> T &
Add a child profile node.
Definition profile.hh:161
Base class for profiling data.
Definition profile.hh:103
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:123
virtual auto score(ProfileType type) const -> double
Get a score for sorting profile nodes.
Definition profile.hh:131
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:107
virtual void combine(ProfileStats &stats, ProfileType type, bool nested) const
Combine stats below this node.
Definition profile.hh:140
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:143
virtual void end_step()
Accumulate the per step stats into the accumulated stats.
Definition profile.hh:137
virtual void begin_step()
Reset the per step statistics.
Definition profile.hh:134
auto equal(ProfileNode const &node) const -> bool
Compare this profile node with another for equality.
Definition profile.hh:128
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:669
ProfileType
Whether to process per step or accumulated profiling data.
Definition profile.hh:20
ProfileDetail
Whether to print profile data into a compact or detailed form.
Definition profile.hh:26
@ accu
Profile data accumulated over all steps.
@ step
Profile data for a single step.
Helper to print indentation.
Definition profile.hh:32
ProfileIndent(size_t level, size_t width=2)
Construct the indent with the given amount.
Definition profile.hh:35
friend auto operator+(ProfileIndent const &indent, size_t add) -> ProfileIndent
Add indentation to the given indent.
Definition profile.hh:46
friend auto operator<<(std::ostream &out, ProfileIndent const &indent) -> std::ostream &
Print the given indentation to the given output stream.
Definition profile.hh:38
friend auto operator+=(ProfileIndent &indent, size_t add) -> ProfileIndent &
Add indentation to the current indent (inplace).
Definition profile.hh:51
The profiling data.
Definition profile.hh:64
uint64_t time_instantiate
The time in nanoseconds spent instantiating.
Definition profile.hh:97
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:75
uint64_t matches
The number of matches produced by the instantiator.
Definition profile.hh:93
void reset()
Reset the profiling data to zero.
Definition profile.hh:69
uint64_t instances
The number of instances produced by the instantiator.
Definition profile.hh:95
uint64_t time_propagate
The time in nanoseconds spent propagating.
Definition profile.hh:99
auto score() const -> double
Compute a score for sorting profile nodes based on time.
Definition profile.hh:88
ProfileStats()=default
The default constructor.