rippled
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 <ripple/app/paths/impl/AmountSpec.h>
24 #include <ripple/basics/IOUAmount.h>
25 #include <ripple/basics/XRPAmount.h>
26 #include <ripple/ledger/PaymentSandbox.h>
27 
28 #include <boost/container/flat_map.hpp>
29 
30 #include <chrono>
31 #include <optional>
32 #include <sstream>
33 
34 namespace ripple {
35 namespace path {
36 namespace 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);
69  numActive.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
90  pushLiquiditySrc(EitherAmount const& eIn, EitherAmount const& eOut)
91  {
92  assert(!liquiditySrcIn.empty());
93  liquiditySrcIn.back().push_back(eIn);
94  liquiditySrcOut.back().push_back(eOut);
95  }
96 
97  void
99  {
100  auto const s = liquiditySrcIn.size();
101  size_t const r = !numActive.empty() ? numActive.back() : 16;
102  liquiditySrcIn.resize(s + 1);
103  liquiditySrcIn.back().reserve(r);
104  liquiditySrcOut.resize(s + 1);
105  liquiditySrcOut.back().reserve(r);
106  }
107  };
108 
110 
111  FlowDebugInfo() = delete;
112  FlowDebugInfo(bool nativeIn, bool nativeOut) : passInfo(nativeIn, nativeOut)
113  {
114  timePoints.reserve(16);
115  counts.reserve(16);
116  passInfo.reserve(64);
117  }
118 
119  auto
120  duration(std::string const& tag) const
121  {
122  auto i = timePoints.find(tag);
123  if (i == timePoints.end())
124  {
125  assert(0);
127  }
128  auto const& t = i->second;
129  return std::chrono::duration_cast<std::chrono::duration<double>>(
130  t.second - t.first);
131  }
132 
134  count(std::string const& tag) const
135  {
136  auto i = counts.find(tag);
137  if (i == counts.end())
138  return 0;
139  return i->second;
140  }
141 
142  // Time the duration of the existence of the result
143  auto
145  {
146  struct Stopper
147  {
148  std::string tag;
149  FlowDebugInfo* info;
150  Stopper(std::string name, FlowDebugInfo& pi)
151  : tag(std::move(name)), info(&pi)
152  {
153  auto const start = FlowDebugInfo::clock::now();
154  info->timePoints.emplace(tag, std::make_pair(start, start));
155  }
156  ~Stopper()
157  {
158  auto const end = FlowDebugInfo::clock::now();
159  info->timePoints[tag].second = end;
160  }
161  Stopper(Stopper&&) = default;
162  };
163  return Stopper(std::move(name), *this);
164  }
165 
166  void
167  inc(std::string const& tag)
168  {
169  auto i = counts.find(tag);
170  if (i == counts.end())
171  {
172  counts[tag] = 1;
173  }
174  ++i->second;
175  }
176 
177  void
179  {
180  counts[tag] = c;
181  }
182 
184  passCount() const
185  {
186  return passInfo.size();
187  }
188 
189  void
191  EitherAmount const& in,
192  EitherAmount const& out,
193  std::size_t activeStrands)
194  {
195  passInfo.push_back(in, out, activeStrands);
196  }
197 
198  void
200  {
202  }
203 
204  void
206  {
208  }
209 
211  to_string(bool writePassInfo) const
212  {
213  std::ostringstream ostr;
214 
215  auto const d = duration("main");
216 
217  ostr << "duration: " << d.count() << ", pass_count: " << passCount();
218 
219  if (writePassInfo)
220  {
221  auto write_list =
222  [&ostr](auto const& vals, auto&& fun, char delim = ';') {
223  ostr << '[';
224  if (!vals.empty())
225  {
226  ostr << fun(vals[0]);
227  for (size_t i = 1, e = vals.size(); i < e; ++i)
228  ostr << delim << fun(vals[i]);
229  }
230  ostr << ']';
231  };
232  auto writeXrpAmtList = [&write_list](
233  std::vector<EitherAmount> const& amts,
234  char delim = ';') {
235  auto get_val = [](EitherAmount const& a) -> std::string {
236  return ripple::to_string(a.xrp);
237  };
238  write_list(amts, get_val, delim);
239  };
240  auto writeIouAmtList = [&write_list](
241  std::vector<EitherAmount> const& amts,
242  char delim = ';') {
243  auto get_val = [](EitherAmount const& a) -> std::string {
244  return ripple::to_string(a.iou);
245  };
246  write_list(amts, get_val, delim);
247  };
248  auto writeIntList = [&write_list](
249  std::vector<size_t> const& vals,
250  char delim = ';') {
251  auto get_val = [](size_t const& v) -> size_t const& {
252  return v;
253  };
254  write_list(vals, get_val);
255  };
256  auto writeNestedIouAmtList =
257  [&ostr, &writeIouAmtList](
259  ostr << '[';
260  if (!amts.empty())
261  {
262  writeIouAmtList(amts[0], '|');
263  for (size_t i = 1, e = amts.size(); i < e; ++i)
264  {
265  ostr << ';';
266  writeIouAmtList(amts[i], '|');
267  }
268  }
269  ostr << ']';
270  };
271  auto writeNestedXrpAmtList =
272  [&ostr, &writeXrpAmtList](
274  ostr << '[';
275  if (!amts.empty())
276  {
277  writeXrpAmtList(amts[0], '|');
278  for (size_t i = 1, e = amts.size(); i < e; ++i)
279  {
280  ostr << ';';
281  writeXrpAmtList(amts[i], '|');
282  }
283  }
284  ostr << ']';
285  };
286 
287  ostr << ", in_pass: ";
288  if (passInfo.nativeIn)
289  writeXrpAmtList(passInfo.in);
290  else
291  writeIouAmtList(passInfo.in);
292  ostr << ", out_pass: ";
293  if (passInfo.nativeOut)
294  writeXrpAmtList(passInfo.out);
295  else
296  writeIouAmtList(passInfo.out);
297  ostr << ", num_active: ";
298  writeIntList(passInfo.numActive);
299  if (!passInfo.liquiditySrcIn.empty() &&
300  !passInfo.liquiditySrcIn.back().empty())
301  {
302  ostr << ", l_src_in: ";
303  if (passInfo.nativeIn)
304  writeNestedXrpAmtList(passInfo.liquiditySrcIn);
305  else
306  writeNestedIouAmtList(passInfo.liquiditySrcIn);
307  ostr << ", l_src_out: ";
308  if (passInfo.nativeOut)
309  writeNestedXrpAmtList(passInfo.liquiditySrcOut);
310  else
311  writeNestedIouAmtList(passInfo.liquiditySrcOut);
312  }
313  }
314 
315  return ostr.str();
316  }
317 };
318 
319 inline void
321  std::ostringstream& ostr,
323 {
324  using namespace std;
325  auto const k = elem.first;
326  auto const v = elem.second;
327  ostr << '[' << get<0>(k) << '|' << get<1>(k) << '|' << get<2>(k) << '|' << v
328  << ']';
329 };
330 
331 template <class Iter>
332 void
333 writeDiffs(std::ostringstream& ostr, Iter begin, Iter end)
334 {
335  ostr << '[';
336  if (begin != end)
337  {
338  writeDiffElement(ostr, *begin);
339  ++begin;
340  }
341  for (; begin != end; ++begin)
342  {
343  ostr << ';';
344  writeDiffElement(ostr, *begin);
345  }
346  ostr << ']';
347 };
348 
349 using BalanceDiffs = std::pair<
352 
353 inline BalanceDiffs
354 balanceDiffs(PaymentSandbox const& sb, ReadView const& rv)
355 {
356  return {sb.balanceChanges(rv), sb.xrpDestroyed()};
357 }
358 
359 inline std::string
361 {
362  if (!bd)
363  return std::string{};
364  auto const& diffs = bd->first;
365  auto const& xrpDestroyed = bd->second;
366  std::ostringstream ostr;
367  ostr << ", xrpDestroyed: " << to_string(xrpDestroyed);
368  ostr << ", balanceDiffs: ";
369  writeDiffs(ostr, diffs.begin(), diffs.end());
370  return ostr.str();
371 };
372 
373 } // namespace detail
374 } // namespace path
375 } // namespace ripple
376 #endif
ripple::path::detail::writeDiffs
void writeDiffs(std::ostringstream &ostr, Iter begin, Iter end)
Definition: FlowDebugInfo.h:333
ripple::path::detail::FlowDebugInfo::PassInfo::nativeIn
const bool nativeIn
Definition: FlowDebugInfo.h:53
ripple::PaymentSandbox::xrpDestroyed
XRPAmount xrpDestroyed() const
Definition: PaymentSandbox.cpp:391
ripple::path::detail::FlowDebugInfo::PassInfo::push_back
void push_back(EitherAmount const &in_amt, EitherAmount const &out_amt, std::size_t active)
Definition: FlowDebugInfo.h:79
sstream
ripple::path::detail::FlowDebugInfo::PassInfo::reserve
void reserve(size_t s)
Definition: FlowDebugInfo.h:63
ripple::path::detail::FlowDebugInfo::pushLiquiditySrc
void pushLiquiditySrc(EitherAmount const &in, EitherAmount const &out)
Definition: FlowDebugInfo.h:199
ripple::path::detail::FlowDebugInfo::timePoints
boost::container::flat_map< std::string, std::pair< time_point, time_point > > timePoints
Definition: FlowDebugInfo.h:43
std::string
STL class.
ripple::path::detail::FlowDebugInfo::newLiquidityPass
void newLiquidityPass()
Definition: FlowDebugInfo.h:205
ripple::PaymentSandbox
A wrapper which makes credits unavailable to balances.
Definition: PaymentSandbox.h:112
ripple::path::detail::FlowDebugInfo
Definition: FlowDebugInfo.h:38
std::pair
std::vector::reserve
T reserve(T... args)
std::vector
STL class.
std::vector::size
T size(T... args)
ripple::path::detail::FlowDebugInfo::PassInfo::numActive
std::vector< size_t > numActive
Definition: FlowDebugInfo.h:57
std::chrono::duration
ripple::path::detail::FlowDebugInfo::inc
void inc(std::string const &tag)
Definition: FlowDebugInfo.h:167
ripple::path::detail::balanceDiffs
BalanceDiffs balanceDiffs(PaymentSandbox const &sb, ReadView const &rv)
Definition: FlowDebugInfo.h:354
ripple::path::detail::BalanceDiffs
std::pair< std::map< std::tuple< AccountID, AccountID, Currency >, STAmount >, XRPAmount > BalanceDiffs
Definition: FlowDebugInfo.h:351
ripple::path::detail::FlowDebugInfo::PassInfo::liquiditySrcOut
std::vector< std::vector< EitherAmount > > liquiditySrcOut
Definition: FlowDebugInfo.h:60
ripple::QualityDirection::in
@ in
ripple::path::detail::FlowDebugInfo::count
std::size_t count(std::string const &tag) const
Definition: FlowDebugInfo.h:134
std::tuple
ripple::path::detail::FlowDebugInfo::passInfo
PassInfo passInfo
Definition: FlowDebugInfo.h:109
std::vector::back
T back(T... args)
ripple::path::detail::FlowDebugInfo::to_string
std::string to_string(bool writePassInfo) const
Definition: FlowDebugInfo.h:211
ripple::PaymentSandbox::balanceChanges
std::map< std::tuple< AccountID, AccountID, Currency >, STAmount > balanceChanges(ReadView const &view) const
Definition: PaymentSandbox.cpp:269
ripple::path::detail::FlowDebugInfo::FlowDebugInfo
FlowDebugInfo()=delete
ripple::path::detail::FlowDebugInfo::duration
auto duration(std::string const &tag) const
Definition: FlowDebugInfo.h:120
std::chrono::high_resolution_clock
ripple::path::detail::FlowDebugInfo::FlowDebugInfo
FlowDebugInfo(bool nativeIn, bool nativeOut)
Definition: FlowDebugInfo.h:112
std::vector::push_back
T push_back(T... args)
ripple::path::detail::FlowDebugInfo::PassInfo::PassInfo
PassInfo(bool nativeIn_, bool nativeOut_)
Definition: FlowDebugInfo.h:49
ripple::path::detail::balanceDiffsToString
std::string balanceDiffsToString(std::optional< BalanceDiffs > const &bd)
Definition: FlowDebugInfo.h:360
ripple::QualityDirection::out
@ out
ripple::path::detail::FlowDebugInfo::timeBlock
auto timeBlock(std::string name)
Definition: FlowDebugInfo.h:144
chrono
ripple::path::detail::FlowDebugInfo::PassInfo::newLiquidityPass
void newLiquidityPass()
Definition: FlowDebugInfo.h:98
ripple::path::detail::FlowDebugInfo::PassInfo::nativeOut
const bool nativeOut
Definition: FlowDebugInfo.h:54
ripple::STAmount
Definition: STAmount.h:45
ripple::path::detail::FlowDebugInfo::PassInfo::liquiditySrcIn
std::vector< std::vector< EitherAmount > > liquiditySrcIn
Definition: FlowDebugInfo.h:59
std::map
STL class.
ripple::path::detail::FlowDebugInfo::setCount
void setCount(std::string const &tag, std::size_t c)
Definition: FlowDebugInfo.h:178
ripple::path::detail::FlowDebugInfo::passCount
std::size_t passCount() const
Definition: FlowDebugInfo.h:184
ripple::path::detail::FlowDebugInfo::PassInfo::pushLiquiditySrc
void pushLiquiditySrc(EitherAmount const &eIn, EitherAmount const &eOut)
Definition: FlowDebugInfo.h:90
ripple::path::detail::FlowDebugInfo::PassInfo::PassInfo
PassInfo()=delete
std::ostringstream
STL class.
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::path::detail::FlowDebugInfo::time_point
clock::time_point time_point
Definition: FlowDebugInfo.h:41
std::begin
T begin(T... args)
ripple::path::detail::writeDiffElement
void writeDiffElement(std::ostringstream &ostr, std::pair< std::tuple< AccountID, AccountID, Currency >, STAmount > const &elem)
Definition: FlowDebugInfo.h:320
std
STL namespace.
ripple::path::detail::FlowDebugInfo::PassInfo
Definition: FlowDebugInfo.h:46
ripple::EitherAmount
Definition: AmountSpec.h:59
std::vector::empty
T empty(T... args)
optional
std::ostringstream::str
T str(T... args)
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::make_pair
T make_pair(T... args)
ripple::path::detail::FlowDebugInfo::pushPass
void pushPass(EitherAmount const &in, EitherAmount const &out, std::size_t activeStrands)
Definition: FlowDebugInfo.h:190
std::end
T end(T... args)
ripple::path::detail::FlowDebugInfo::counts
boost::container::flat_map< std::string, std::size_t > counts
Definition: FlowDebugInfo.h:44
ripple::path::detail::FlowDebugInfo::PassInfo::in
std::vector< EitherAmount > in
Definition: FlowDebugInfo.h:55
ripple::path::detail::FlowDebugInfo::PassInfo::out
std::vector< EitherAmount > out
Definition: FlowDebugInfo.h:56
ripple::path::detail::FlowDebugInfo::PassInfo::size
size_t size() const
Definition: FlowDebugInfo.h:73
ripple::XRPAmount
Definition: XRPAmount.h:46
std::chrono::high_resolution_clock::now
T now(T... args)