xrpld
Loading...
Searching...
No Matches
FlowDebugInfo.h
1#pragma once
2
3#include <xrpl/ledger/PaymentSandbox.h>
4#include <xrpl/protocol/IOUAmount.h>
5#include <xrpl/protocol/XRPAmount.h>
6
7#include <boost/container/flat_map.hpp>
8
9#include <chrono>
10#include <optional>
11#include <sstream>
12
14// Track performance information of a single payment
16{
18 using time_point = clock::time_point;
19 boost::container::flat_map<std::string, std::pair<time_point, time_point>> timePoints;
20 boost::container::flat_map<std::string, std::size_t> counts;
21
22 struct PassInfo
23 {
24 PassInfo() = delete;
28 bool const nativeIn;
29 bool const nativeOut;
33
36
37 void
38 reserve(size_t s)
39 {
40 in.reserve(s);
41 out.reserve(s);
42 liquiditySrcIn.reserve(s);
43 liquiditySrcOut.reserve(s);
44 numActive.reserve(s);
45 }
46
47 [[nodiscard]] size_t
48 size() const
49 {
50 return in.size();
51 }
52
53 void
54 pushBack(EitherAmount const& inAmt, EitherAmount const& outAmt, std::size_t active)
55 {
56 in.push_back(inAmt);
57 out.push_back(outAmt);
58 numActive.push_back(active);
59 }
60
61 void
63 {
64 XRPL_ASSERT(
65 !liquiditySrcIn.empty(),
66 "xrpl::path::detail::FlowDebugInfo::pushLiquiditySrc : "
67 "non-empty liquidity source");
68 liquiditySrcIn.back().push_back(eIn);
69 liquiditySrcOut.back().push_back(eOut);
70 }
71
72 void
74 {
75 auto const s = liquiditySrcIn.size();
76 size_t const r = !numActive.empty() ? numActive.back() : 16;
77 liquiditySrcIn.resize(s + 1);
78 liquiditySrcIn.back().reserve(r);
79 liquiditySrcOut.resize(s + 1);
80 liquiditySrcOut.back().reserve(r);
81 }
82 };
83
85
86 FlowDebugInfo() = delete;
87 FlowDebugInfo(bool nativeIn, bool nativeOut) : passInfo(nativeIn, nativeOut)
88 {
89 timePoints.reserve(16);
90 counts.reserve(16);
91 passInfo.reserve(64);
92 }
93
94 [[nodiscard]] auto
95 duration(std::string const& tag) const
96 {
97 auto i = timePoints.find(tag);
98 if (i == timePoints.end())
99 {
100 // LCOV_EXCL_START
101 UNREACHABLE(
102 "xrpl::path::detail::FlowDebugInfo::duration : timepoint not "
103 "found");
105 // LCOV_EXCL_STOP
106 }
107 auto const& t = i->second;
109 }
110
111 [[nodiscard]] std::size_t
112 count(std::string const& tag) const
113 {
114 auto i = counts.find(tag);
115 if (i == counts.end())
116 return 0;
117 return i->second;
118 }
119
120 // Time the duration of the existence of the result
121 auto
123 {
124 struct Stopper
125 {
126 std::string tag;
127 FlowDebugInfo* info;
128 Stopper(std::string name, FlowDebugInfo& pi) : tag(std::move(name)), info(&pi)
129 {
130 auto const start = FlowDebugInfo::clock::now();
131 info->timePoints.emplace(tag, std::make_pair(start, start));
132 }
133 ~Stopper()
134 {
135 auto const end = FlowDebugInfo::clock::now();
136 info->timePoints[tag].second = end;
137 }
138 Stopper(Stopper&&) = default;
139 };
140 return Stopper(std::move(name), *this);
141 }
142
143 void
144 inc(std::string const& tag)
145 {
146 auto i = counts.find(tag);
147 if (i == counts.end())
148 {
149 counts[tag] = 1;
150 }
151 ++i->second;
152 }
153
154 void
156 {
157 counts[tag] = c;
158 }
159
160 [[nodiscard]] std::size_t
161 passCount() const
162 {
163 return passInfo.size();
164 }
165
166 void
167 pushPass(EitherAmount const& in, EitherAmount const& out, std::size_t activeStrands)
168 {
169 passInfo.pushBack(in, out, activeStrands);
170 }
171
172 void
174 {
175 passInfo.pushLiquiditySrc(in, out);
176 }
177
178 void
180 {
181 passInfo.newLiquidityPass();
182 }
183
184 [[nodiscard]] std::string
185 toString(bool writePassInfo) const
186 {
188
189 auto const d = duration("main");
190
191 ostr << "duration: " << d.count() << ", pass_count: " << passCount();
192
193 if (writePassInfo)
194 {
195 auto writeList = [&ostr](auto const& vals, auto&& fun, char delim = ';') {
196 ostr << '[';
197 if (!vals.empty())
198 {
199 ostr << fun(vals[0]);
200 for (size_t i = 1, e = vals.size(); i < e; ++i)
201 ostr << delim << fun(vals[i]);
202 }
203 ostr << ']';
204 };
205 auto writeXrpAmtList = [&writeList](
206 std::vector<EitherAmount> const& amts, char delim = ';') {
207 auto getVal = [](EitherAmount const& a) -> std::string {
208 return xrpl::to_string(a.get<XRPAmount>());
209 };
210 writeList(amts, getVal, delim);
211 };
212 auto writeIouAmtList = [&writeList](
213 std::vector<EitherAmount> const& amts, char delim = ';') {
214 auto getVal = [](EitherAmount const& a) -> std::string {
215 return xrpl::to_string(a.get<IOUAmount>());
216 };
217 writeList(amts, getVal, delim);
218 };
219 auto writeIntList = [&writeList](std::vector<size_t> const& vals, char delim = ';') {
220 // NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
221 auto getVal = [](size_t const& v) -> size_t const& { return v; };
222 writeList(vals, getVal);
223 };
224 auto writeNestedIouAmtList =
225 [&ostr, &writeIouAmtList](std::vector<std::vector<EitherAmount>> const& amts) {
226 ostr << '[';
227 if (!amts.empty())
228 {
229 writeIouAmtList(amts[0], '|');
230 for (size_t i = 1, e = amts.size(); i < e; ++i)
231 {
232 ostr << ';';
233 writeIouAmtList(amts[i], '|');
234 }
235 }
236 ostr << ']';
237 };
238 auto writeNestedXrpAmtList =
239 [&ostr, &writeXrpAmtList](std::vector<std::vector<EitherAmount>> const& amts) {
240 ostr << '[';
241 if (!amts.empty())
242 {
243 writeXrpAmtList(amts[0], '|');
244 for (size_t i = 1, e = amts.size(); i < e; ++i)
245 {
246 ostr << ';';
247 writeXrpAmtList(amts[i], '|');
248 }
249 }
250 ostr << ']';
251 };
252
253 ostr << ", in_pass: ";
254 if (passInfo.nativeIn)
255 {
256 writeXrpAmtList(passInfo.in);
257 }
258 else
259 {
260 writeIouAmtList(passInfo.in);
261 }
262 ostr << ", out_pass: ";
263 if (passInfo.nativeOut)
264 {
265 writeXrpAmtList(passInfo.out);
266 }
267 else
268 {
269 writeIouAmtList(passInfo.out);
270 }
271 ostr << ", num_active: ";
272 writeIntList(passInfo.numActive);
273 if (!passInfo.liquiditySrcIn.empty() && !passInfo.liquiditySrcIn.back().empty())
274 {
275 ostr << ", l_src_in: ";
276 if (passInfo.nativeIn)
277 {
278 writeNestedXrpAmtList(passInfo.liquiditySrcIn);
279 }
280 else
281 {
282 writeNestedIouAmtList(passInfo.liquiditySrcIn);
283 }
284 ostr << ", l_src_out: ";
285 if (passInfo.nativeOut)
286 {
287 writeNestedXrpAmtList(passInfo.liquiditySrcOut);
288 }
289 else
290 {
291 writeNestedIouAmtList(passInfo.liquiditySrcOut);
292 }
293 }
294 }
295
296 return ostr.str();
297 }
298};
299
300inline void
302 std::ostringstream& ostr,
304{
305 using namespace std;
306 auto const k = elem.first;
307 auto const v = elem.second;
308 ostr << '[' << get<0>(k) << '|' << get<1>(k) << '|' << get<2>(k) << '|' << v << ']';
309};
310
311template <class Iter>
312void
314{
315 ostr << '[';
316 if (begin != end)
317 {
318 writeDiffElement(ostr, *begin);
319 ++begin;
320 }
321 for (; begin != end; ++begin)
322 {
323 ostr << ';';
324 writeDiffElement(ostr, *begin);
325 }
326 ostr << ']';
327};
328
329} // namespace xrpl::path::detail
T begin(T... args)
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:24
T duration_cast(T... args)
T empty(T... args)
T end(T... args)
T make_pair(T... args)
STL namespace.
void writeDiffs(std::ostringstream &ostr, Iter begin, Iter end)
void writeDiffElement(std::ostringstream &ostr, std::pair< std::tuple< AccountID, AccountID, Currency >, STAmount > const &elem)
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
T size(T... args)
T str(T... args)
std::vector< std::vector< EitherAmount > > liquiditySrcOut
void pushBack(EitherAmount const &inAmt, EitherAmount const &outAmt, std::size_t active)
void pushLiquiditySrc(EitherAmount const &eIn, EitherAmount const &eOut)
PassInfo(bool nativeIn, bool nativeOut)
std::vector< std::vector< EitherAmount > > liquiditySrcIn
void pushPass(EitherAmount const &in, EitherAmount const &out, std::size_t activeStrands)
void pushLiquiditySrc(EitherAmount const &in, EitherAmount const &out)
std::string toString(bool writePassInfo) const
std::size_t count(std::string const &tag) const
FlowDebugInfo(bool nativeIn, bool nativeOut)
boost::container::flat_map< std::string, std::size_t > counts
void inc(std::string const &tag)
void setCount(std::string const &tag, std::size_t c)
auto duration(std::string const &tag) const
auto timeBlock(std::string name)
std::chrono::high_resolution_clock clock
boost::container::flat_map< std::string, std::pair< time_point, time_point > > timePoints