rippled
Loading...
Searching...
No Matches
FlowDebugInfo.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_PATH_IMPL_FLOWDEBUGINFO_H_INCLUDED
21#define RIPPLE_PATH_IMPL_FLOWDEBUGINFO_H_INCLUDED
22
23#include <xrpld/app/paths/detail/AmountSpec.h>
24#include <xrpld/ledger/PaymentSandbox.h>
25
26#include <xrpl/protocol/IOUAmount.h>
27#include <xrpl/protocol/XRPAmount.h>
28
29#include <boost/container/flat_map.hpp>
30
31#include <chrono>
32#include <optional>
33#include <sstream>
34
35namespace ripple {
36namespace path {
37namespace detail {
38// Track performance information of a single payment
40{
42 using time_point = clock::time_point;
43 boost::container::flat_map<std::string, std::pair<time_point, time_point>>
45 boost::container::flat_map<std::string, std::size_t> counts;
46
47 struct PassInfo
48 {
49 PassInfo() = delete;
50 PassInfo(bool nativeIn_, bool nativeOut_)
51 : nativeIn(nativeIn_), nativeOut(nativeOut_)
52 {
53 }
54 bool const nativeIn;
55 bool const nativeOut;
59
62
63 void
64 reserve(size_t s)
65 {
66 in.reserve(s);
67 out.reserve(s);
68 liquiditySrcIn.reserve(s);
69 liquiditySrcOut.reserve(s);
71 }
72
73 size_t
74 size() const
75 {
76 return in.size();
77 }
78
79 void
81 EitherAmount const& in_amt,
82 EitherAmount const& out_amt,
83 std::size_t active)
84 {
85 in.push_back(in_amt);
86 out.push_back(out_amt);
87 numActive.push_back(active);
88 }
89
90 void
92 {
93 XRPL_ASSERT(
94 !liquiditySrcIn.empty(),
95 "ripple::path::detail::FlowDebugInfo::pushLiquiditySrc : "
96 "non-empty liquidity source");
97 liquiditySrcIn.back().push_back(eIn);
98 liquiditySrcOut.back().push_back(eOut);
99 }
100
101 void
103 {
104 auto const s = liquiditySrcIn.size();
105 size_t const r = !numActive.empty() ? numActive.back() : 16;
106 liquiditySrcIn.resize(s + 1);
107 liquiditySrcIn.back().reserve(r);
108 liquiditySrcOut.resize(s + 1);
109 liquiditySrcOut.back().reserve(r);
110 }
111 };
112
114
115 FlowDebugInfo() = delete;
116 FlowDebugInfo(bool nativeIn, bool nativeOut) : passInfo(nativeIn, nativeOut)
117 {
118 timePoints.reserve(16);
119 counts.reserve(16);
120 passInfo.reserve(64);
121 }
122
123 auto
124 duration(std::string const& tag) const
125 {
126 auto i = timePoints.find(tag);
127 if (i == timePoints.end())
128 {
129 UNREACHABLE(
130 "ripple::path::detail::FlowDebugInfo::duration : timepoint not "
131 "found");
133 }
134 auto const& t = i->second;
135 return std::chrono::duration_cast<std::chrono::duration<double>>(
136 t.second - t.first);
137 }
138
140 count(std::string const& tag) const
141 {
142 auto i = counts.find(tag);
143 if (i == counts.end())
144 return 0;
145 return i->second;
146 }
147
148 // Time the duration of the existence of the result
149 auto
151 {
152 struct Stopper
153 {
154 std::string tag;
155 FlowDebugInfo* info;
156 Stopper(std::string name, FlowDebugInfo& pi)
157 : tag(std::move(name)), info(&pi)
158 {
159 auto const start = FlowDebugInfo::clock::now();
160 info->timePoints.emplace(tag, std::make_pair(start, start));
161 }
162 ~Stopper()
163 {
164 auto const end = FlowDebugInfo::clock::now();
165 info->timePoints[tag].second = end;
166 }
167 Stopper(Stopper&&) = default;
168 };
169 return Stopper(std::move(name), *this);
170 }
171
172 void
173 inc(std::string const& tag)
174 {
175 auto i = counts.find(tag);
176 if (i == counts.end())
177 {
178 counts[tag] = 1;
179 }
180 ++i->second;
181 }
182
183 void
185 {
186 counts[tag] = c;
187 }
188
190 passCount() const
191 {
192 return passInfo.size();
193 }
194
195 void
197 EitherAmount const& in,
198 EitherAmount const& out,
199 std::size_t activeStrands)
200 {
201 passInfo.push_back(in, out, activeStrands);
202 }
203
204 void
206 {
208 }
209
210 void
212 {
214 }
215
217 to_string(bool writePassInfo) const
218 {
220
221 auto const d = duration("main");
222
223 ostr << "duration: " << d.count() << ", pass_count: " << passCount();
224
225 if (writePassInfo)
226 {
227 auto write_list =
228 [&ostr](auto const& vals, auto&& fun, char delim = ';') {
229 ostr << '[';
230 if (!vals.empty())
231 {
232 ostr << fun(vals[0]);
233 for (size_t i = 1, e = vals.size(); i < e; ++i)
234 ostr << delim << fun(vals[i]);
235 }
236 ostr << ']';
237 };
238 auto writeXrpAmtList = [&write_list](
239 std::vector<EitherAmount> const& amts,
240 char delim = ';') {
241 auto get_val = [](EitherAmount const& a) -> std::string {
242 return ripple::to_string(a.xrp);
243 };
244 write_list(amts, get_val, delim);
245 };
246 auto writeIouAmtList = [&write_list](
247 std::vector<EitherAmount> const& amts,
248 char delim = ';') {
249 auto get_val = [](EitherAmount const& a) -> std::string {
250 return ripple::to_string(a.iou);
251 };
252 write_list(amts, get_val, delim);
253 };
254 auto writeIntList = [&write_list](
255 std::vector<size_t> const& vals,
256 char delim = ';') {
257 auto get_val = [](size_t const& v) -> size_t const& {
258 return v;
259 };
260 write_list(vals, get_val);
261 };
262 auto writeNestedIouAmtList =
263 [&ostr, &writeIouAmtList](
265 ostr << '[';
266 if (!amts.empty())
267 {
268 writeIouAmtList(amts[0], '|');
269 for (size_t i = 1, e = amts.size(); i < e; ++i)
270 {
271 ostr << ';';
272 writeIouAmtList(amts[i], '|');
273 }
274 }
275 ostr << ']';
276 };
277 auto writeNestedXrpAmtList =
278 [&ostr, &writeXrpAmtList](
280 ostr << '[';
281 if (!amts.empty())
282 {
283 writeXrpAmtList(amts[0], '|');
284 for (size_t i = 1, e = amts.size(); i < e; ++i)
285 {
286 ostr << ';';
287 writeXrpAmtList(amts[i], '|');
288 }
289 }
290 ostr << ']';
291 };
292
293 ostr << ", in_pass: ";
294 if (passInfo.nativeIn)
295 writeXrpAmtList(passInfo.in);
296 else
297 writeIouAmtList(passInfo.in);
298 ostr << ", out_pass: ";
300 writeXrpAmtList(passInfo.out);
301 else
302 writeIouAmtList(passInfo.out);
303 ostr << ", num_active: ";
304 writeIntList(passInfo.numActive);
305 if (!passInfo.liquiditySrcIn.empty() &&
306 !passInfo.liquiditySrcIn.back().empty())
307 {
308 ostr << ", l_src_in: ";
309 if (passInfo.nativeIn)
310 writeNestedXrpAmtList(passInfo.liquiditySrcIn);
311 else
312 writeNestedIouAmtList(passInfo.liquiditySrcIn);
313 ostr << ", l_src_out: ";
315 writeNestedXrpAmtList(passInfo.liquiditySrcOut);
316 else
317 writeNestedIouAmtList(passInfo.liquiditySrcOut);
318 }
319 }
320
321 return ostr.str();
322 }
323};
324
325inline void
327 std::ostringstream& ostr,
329{
330 using namespace std;
331 auto const k = elem.first;
332 auto const v = elem.second;
333 ostr << '[' << get<0>(k) << '|' << get<1>(k) << '|' << get<2>(k) << '|' << v
334 << ']';
335};
336
337template <class Iter>
338void
339writeDiffs(std::ostringstream& ostr, Iter begin, Iter end)
340{
341 ostr << '[';
342 if (begin != end)
343 {
344 writeDiffElement(ostr, *begin);
345 ++begin;
346 }
347 for (; begin != end; ++begin)
348 {
349 ostr << ';';
350 writeDiffElement(ostr, *begin);
351 }
352 ostr << ']';
353};
354
357 XRPAmount>;
358
359inline BalanceDiffs
361{
362 return {sb.balanceChanges(rv), sb.xrpDestroyed()};
363}
364
365inline std::string
367{
368 if (!bd)
369 return std::string{};
370 auto const& diffs = bd->first;
371 auto const& xrpDestroyed = bd->second;
373 ostr << ", xrpDestroyed: " << to_string(xrpDestroyed);
374 ostr << ", balanceDiffs: ";
375 writeDiffs(ostr, diffs.begin(), diffs.end());
376 return ostr.str();
377};
378
379} // namespace detail
380} // namespace path
381} // namespace ripple
382#endif
T back(T... args)
A wrapper which makes credits unavailable to balances.
XRPAmount xrpDestroyed() const
std::map< std::tuple< AccountID, AccountID, Currency >, STAmount > balanceChanges(ReadView const &view) const
A view into a ledger.
Definition: ReadView.h:52
T empty(T... args)
T make_pair(T... args)
void writeDiffElement(std::ostringstream &ostr, std::pair< std::tuple< AccountID, AccountID, Currency >, STAmount > const &elem)
std::string balanceDiffsToString(std::optional< BalanceDiffs > const &bd)
BalanceDiffs balanceDiffs(PaymentSandbox const &sb, ReadView const &rv)
void writeDiffs(std::ostringstream &ostr, Iter begin, Iter end)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
STL namespace.
T push_back(T... args)
T reserve(T... args)
T size(T... args)
T str(T... args)
PassInfo(bool nativeIn_, bool nativeOut_)
Definition: FlowDebugInfo.h:50
std::vector< std::vector< EitherAmount > > liquiditySrcIn
Definition: FlowDebugInfo.h:60
std::vector< std::vector< EitherAmount > > liquiditySrcOut
Definition: FlowDebugInfo.h:61
void pushLiquiditySrc(EitherAmount const &eIn, EitherAmount const &eOut)
Definition: FlowDebugInfo.h:91
void push_back(EitherAmount const &in_amt, EitherAmount const &out_amt, std::size_t active)
Definition: FlowDebugInfo.h:80
std::string to_string(bool writePassInfo) const
auto timeBlock(std::string name)
void pushPass(EitherAmount const &in, EitherAmount const &out, std::size_t activeStrands)
auto duration(std::string const &tag) const
std::size_t count(std::string const &tag) const
void pushLiquiditySrc(EitherAmount const &in, EitherAmount const &out)
FlowDebugInfo(bool nativeIn, bool nativeOut)
void inc(std::string const &tag)
boost::container::flat_map< std::string, std::size_t > counts
Definition: FlowDebugInfo.h:45
boost::container::flat_map< std::string, std::pair< time_point, time_point > > timePoints
Definition: FlowDebugInfo.h:44
void setCount(std::string const &tag, std::size_t c)