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#include <xrpl/protocol/IOUAmount.h>
26#include <xrpl/protocol/XRPAmount.h>
27
28#include <boost/container/flat_map.hpp>
29
30#include <chrono>
31#include <optional>
32#include <sstream>
33
34namespace ripple {
35namespace path {
36namespace detail {
37// Track performance information of a single payment
39{
41 using time_point = clock::time_point;
42 boost::container::flat_map<std::string, std::pair<time_point, time_point>>
44 boost::container::flat_map<std::string, std::size_t> counts;
45
46 struct PassInfo
47 {
48 PassInfo() = delete;
49 PassInfo(bool nativeIn_, bool nativeOut_)
50 : nativeIn(nativeIn_), nativeOut(nativeOut_)
51 {
52 }
53 bool const nativeIn;
54 bool const nativeOut;
58
61
62 void
63 reserve(size_t s)
64 {
65 in.reserve(s);
66 out.reserve(s);
67 liquiditySrcIn.reserve(s);
68 liquiditySrcOut.reserve(s);
70 }
71
72 size_t
73 size() const
74 {
75 return in.size();
76 }
77
78 void
80 EitherAmount const& in_amt,
81 EitherAmount const& out_amt,
82 std::size_t active)
83 {
84 in.push_back(in_amt);
85 out.push_back(out_amt);
86 numActive.push_back(active);
87 }
88
89 void
91 {
92 XRPL_ASSERT(
93 !liquiditySrcIn.empty(),
94 "ripple::path::detail::FlowDebugInfo::pushLiquiditySrc : "
95 "non-empty liquidity source");
96 liquiditySrcIn.back().push_back(eIn);
97 liquiditySrcOut.back().push_back(eOut);
98 }
99
100 void
102 {
103 auto const s = liquiditySrcIn.size();
104 size_t const r = !numActive.empty() ? numActive.back() : 16;
105 liquiditySrcIn.resize(s + 1);
106 liquiditySrcIn.back().reserve(r);
107 liquiditySrcOut.resize(s + 1);
108 liquiditySrcOut.back().reserve(r);
109 }
110 };
111
113
114 FlowDebugInfo() = delete;
115 FlowDebugInfo(bool nativeIn, bool nativeOut) : passInfo(nativeIn, nativeOut)
116 {
117 timePoints.reserve(16);
118 counts.reserve(16);
119 passInfo.reserve(64);
120 }
121
122 auto
123 duration(std::string const& tag) const
124 {
125 auto i = timePoints.find(tag);
126 if (i == timePoints.end())
127 {
128 UNREACHABLE(
129 "ripple::path::detail::FlowDebugInfo::duration : timepoint not "
130 "found");
132 }
133 auto const& t = i->second;
134 return std::chrono::duration_cast<std::chrono::duration<double>>(
135 t.second - t.first);
136 }
137
139 count(std::string const& tag) const
140 {
141 auto i = counts.find(tag);
142 if (i == counts.end())
143 return 0;
144 return i->second;
145 }
146
147 // Time the duration of the existence of the result
148 auto
150 {
151 struct Stopper
152 {
153 std::string tag;
154 FlowDebugInfo* info;
155 Stopper(std::string name, FlowDebugInfo& pi)
156 : tag(std::move(name)), info(&pi)
157 {
158 auto const start = FlowDebugInfo::clock::now();
159 info->timePoints.emplace(tag, std::make_pair(start, start));
160 }
161 ~Stopper()
162 {
163 auto const end = FlowDebugInfo::clock::now();
164 info->timePoints[tag].second = end;
165 }
166 Stopper(Stopper&&) = default;
167 };
168 return Stopper(std::move(name), *this);
169 }
170
171 void
172 inc(std::string const& tag)
173 {
174 auto i = counts.find(tag);
175 if (i == counts.end())
176 {
177 counts[tag] = 1;
178 }
179 ++i->second;
180 }
181
182 void
184 {
185 counts[tag] = c;
186 }
187
189 passCount() const
190 {
191 return passInfo.size();
192 }
193
194 void
196 EitherAmount const& in,
197 EitherAmount const& out,
198 std::size_t activeStrands)
199 {
200 passInfo.push_back(in, out, activeStrands);
201 }
202
203 void
205 {
207 }
208
209 void
211 {
213 }
214
216 to_string(bool writePassInfo) const
217 {
219
220 auto const d = duration("main");
221
222 ostr << "duration: " << d.count() << ", pass_count: " << passCount();
223
224 if (writePassInfo)
225 {
226 auto write_list =
227 [&ostr](auto const& vals, auto&& fun, char delim = ';') {
228 ostr << '[';
229 if (!vals.empty())
230 {
231 ostr << fun(vals[0]);
232 for (size_t i = 1, e = vals.size(); i < e; ++i)
233 ostr << delim << fun(vals[i]);
234 }
235 ostr << ']';
236 };
237 auto writeXrpAmtList = [&write_list](
238 std::vector<EitherAmount> const& amts,
239 char delim = ';') {
240 auto get_val = [](EitherAmount const& a) -> std::string {
241 return ripple::to_string(a.xrp);
242 };
243 write_list(amts, get_val, delim);
244 };
245 auto writeIouAmtList = [&write_list](
246 std::vector<EitherAmount> const& amts,
247 char delim = ';') {
248 auto get_val = [](EitherAmount const& a) -> std::string {
249 return ripple::to_string(a.iou);
250 };
251 write_list(amts, get_val, delim);
252 };
253 auto writeIntList = [&write_list](
254 std::vector<size_t> const& vals,
255 char delim = ';') {
256 auto get_val = [](size_t const& v) -> size_t const& {
257 return v;
258 };
259 write_list(vals, get_val);
260 };
261 auto writeNestedIouAmtList =
262 [&ostr, &writeIouAmtList](
264 ostr << '[';
265 if (!amts.empty())
266 {
267 writeIouAmtList(amts[0], '|');
268 for (size_t i = 1, e = amts.size(); i < e; ++i)
269 {
270 ostr << ';';
271 writeIouAmtList(amts[i], '|');
272 }
273 }
274 ostr << ']';
275 };
276 auto writeNestedXrpAmtList =
277 [&ostr, &writeXrpAmtList](
279 ostr << '[';
280 if (!amts.empty())
281 {
282 writeXrpAmtList(amts[0], '|');
283 for (size_t i = 1, e = amts.size(); i < e; ++i)
284 {
285 ostr << ';';
286 writeXrpAmtList(amts[i], '|');
287 }
288 }
289 ostr << ']';
290 };
291
292 ostr << ", in_pass: ";
293 if (passInfo.nativeIn)
294 writeXrpAmtList(passInfo.in);
295 else
296 writeIouAmtList(passInfo.in);
297 ostr << ", out_pass: ";
299 writeXrpAmtList(passInfo.out);
300 else
301 writeIouAmtList(passInfo.out);
302 ostr << ", num_active: ";
303 writeIntList(passInfo.numActive);
304 if (!passInfo.liquiditySrcIn.empty() &&
305 !passInfo.liquiditySrcIn.back().empty())
306 {
307 ostr << ", l_src_in: ";
308 if (passInfo.nativeIn)
309 writeNestedXrpAmtList(passInfo.liquiditySrcIn);
310 else
311 writeNestedIouAmtList(passInfo.liquiditySrcIn);
312 ostr << ", l_src_out: ";
314 writeNestedXrpAmtList(passInfo.liquiditySrcOut);
315 else
316 writeNestedIouAmtList(passInfo.liquiditySrcOut);
317 }
318 }
319
320 return ostr.str();
321 }
322};
323
324inline void
326 std::ostringstream& ostr,
328{
329 using namespace std;
330 auto const k = elem.first;
331 auto const v = elem.second;
332 ostr << '[' << get<0>(k) << '|' << get<1>(k) << '|' << get<2>(k) << '|' << v
333 << ']';
334};
335
336template <class Iter>
337void
338writeDiffs(std::ostringstream& ostr, Iter begin, Iter end)
339{
340 ostr << '[';
341 if (begin != end)
342 {
343 writeDiffElement(ostr, *begin);
344 ++begin;
345 }
346 for (; begin != end; ++begin)
347 {
348 ostr << ';';
349 writeDiffElement(ostr, *begin);
350 }
351 ostr << ']';
352};
353
356 XRPAmount>;
357
358inline BalanceDiffs
360{
361 return {sb.balanceChanges(rv), sb.xrpDestroyed()};
362}
363
364inline std::string
366{
367 if (!bd)
368 return std::string{};
369 auto const& diffs = bd->first;
370 auto const& xrpDestroyed = bd->second;
372 ostr << ", xrpDestroyed: " << to_string(xrpDestroyed);
373 ostr << ", balanceDiffs: ";
374 writeDiffs(ostr, diffs.begin(), diffs.end());
375 return ostr.str();
376};
377
378} // namespace detail
379} // namespace path
380} // namespace ripple
381#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:55
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:629
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:49
std::vector< std::vector< EitherAmount > > liquiditySrcIn
Definition: FlowDebugInfo.h:59
std::vector< std::vector< EitherAmount > > liquiditySrcOut
Definition: FlowDebugInfo.h:60
void pushLiquiditySrc(EitherAmount const &eIn, EitherAmount const &eOut)
Definition: FlowDebugInfo.h:90
void push_back(EitherAmount const &in_amt, EitherAmount const &out_amt, std::size_t active)
Definition: FlowDebugInfo.h:79
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:44
boost::container::flat_map< std::string, std::pair< time_point, time_point > > timePoints
Definition: FlowDebugInfo.h:43
void setCount(std::string const &tag, std::size_t c)