rippled
Loading...
Searching...
No Matches
collectors.h
1#ifndef XRPL_TEST_CSF_COLLECTORS_H_INCLUDED
2#define XRPL_TEST_CSF_COLLECTORS_H_INCLUDED
3
4#include <test/csf/Histogram.h>
5#include <test/csf/SimTime.h>
6#include <test/csf/events.h>
7
8#include <xrpl/basics/UnorderedContainers.h>
9
10#include <chrono>
11#include <optional>
12#include <ostream>
13#include <tuple>
14
15namespace ripple {
16namespace test {
17namespace csf {
18
19// A collector is any class that implements
20//
21// on(NodeID, SimTime, Event)
22//
23// for all events emitted by a Peer.
24//
25// This file contains helper functions for composing different collectors
26// and also defines several standard collectors available for simulations.
27
35template <class... Cs>
37{
38 std::tuple<Cs&...> cs;
39
40 template <class C, class E>
41 static void
42 apply(C& c, PeerID who, SimTime when, E e)
43 {
44 c.on(who, when, e);
45 }
46
47 template <std::size_t... Is, class E>
48 static void
51 PeerID who,
52 SimTime when,
53 E e,
55 {
56 (..., apply(std::get<Is>(cs), who, when, e));
57 }
58
59public:
64 Collectors(Cs&... cs_) : cs(std::tie(cs_...))
65 {
66 }
67
68 template <class E>
69 void
70 on(PeerID who, SimTime when, E e)
71 {
72 apply(cs, who, when, e, std::index_sequence_for<Cs...>{});
73 }
74};
75
77template <class... Cs>
78Collectors<Cs...>
80{
81 return Collectors<Cs...>(cs...);
82}
83
92template <class CollectorType>
94{
96
97 CollectorType&
99 {
100 return byNode[who];
101 }
102
103 CollectorType const&
105 {
106 return byNode[who];
107 }
108 template <class E>
109 void
110 on(PeerID who, SimTime when, E const& e)
111 {
112 byNode[who].on(who, when, e);
113 }
114};
115
118{
119 template <class E>
120 void
121 on(PeerID, SimTime, E const& e)
122 {
123 }
124};
125
128{
129 bool init = false;
132
133 template <class E>
134 void
135 on(PeerID, SimTime when, E const& e)
136 {
137 if (!init)
138 {
139 start = when;
140 init = true;
141 }
142 else
143 stop = when;
144 }
145};
146
157{
158 // Counts
162
174
176
180
181 // Ignore most events by default
182 template <class E>
183 void
184 on(PeerID, SimTime when, E const& e)
185 {
186 }
187
188 void
189 on(PeerID who, SimTime when, SubmitTx const& e)
190 {
191 // save first time it was seen
192 if (txs.emplace(e.tx.id(), Tracker{e.tx, when}).second)
193 {
194 submitted++;
195 }
196 }
197
198 void
199 on(PeerID who, SimTime when, AcceptLedger const& e)
200 {
201 for (auto const& tx : e.ledger.txs())
202 {
203 auto it = txs.find(tx.id());
204 if (it != txs.end() && !it->second.accepted)
205 {
206 Tracker& tracker = it->second;
207 tracker.accepted = when;
208 accepted++;
209
210 submitToAccept.insert(*tracker.accepted - tracker.submitted);
211 }
212 }
213 }
214
215 void
217 {
218 for (auto const& tx : e.ledger.txs())
219 {
220 auto it = txs.find(tx.id());
221 if (it != txs.end() && !it->second.validated)
222 {
223 Tracker& tracker = it->second;
224 // Should only validated a previously accepted Tx
225 assert(tracker.accepted);
226
227 tracker.validated = when;
228 validated++;
229 submitToValidate.insert(*tracker.validated - tracker.submitted);
230 }
231 }
232 }
233
234 // Returns the number of txs which were never accepted
236 orphaned() const
237 {
238 return std::count_if(txs.begin(), txs.end(), [](auto const& it) {
239 return !it.second.accepted;
240 });
241 }
242
243 // Returns the number of txs which were never validated
246 {
247 return std::count_if(txs.begin(), txs.end(), [](auto const& it) {
248 return !it.second.validated;
249 });
250 }
251
252 template <class T>
253 void
254 report(SimDuration simDuration, T& log, bool printBreakline = false)
255 {
256 using namespace std::chrono;
257 auto perSec = [&simDuration](std::size_t count) {
258 return double(count) / duration_cast<seconds>(simDuration).count();
259 };
260
261 auto fmtS = [](SimDuration dur) {
262 return duration_cast<duration<float>>(dur).count();
263 };
264
265 if (printBreakline)
266 {
267 log << std::setw(11) << std::setfill('-') << "-" << "-"
268 << std::setw(7) << std::setfill('-') << "-" << "-"
269 << std::setw(7) << std::setfill('-') << "-" << "-"
270 << std::setw(36) << std::setfill('-') << "-" << std::endl;
271 log << std::setfill(' ');
272 }
273
274 log << std::left << std::setw(11) << "TxStats" << "|" << std::setw(7)
275 << "Count" << "|" << std::setw(7) << "Per Sec" << "|"
276 << std::setw(15) << "Latency (sec)" << std::right << std::setw(7)
277 << "10-ile" << std::setw(7) << "50-ile" << std::setw(7) << "90-ile"
278 << std::left << std::endl;
279
280 log << std::setw(11) << std::setfill('-') << "-" << "|" << std::setw(7)
281 << std::setfill('-') << "-" << "|" << std::setw(7)
282 << std::setfill('-') << "-" << "|" << std::setw(36)
283 << std::setfill('-') << "-" << std::endl;
284 log << std::setfill(' ');
285
286 log << std::left << std::setw(11) << "Submit " << "|" << std::right
287 << std::setw(7) << submitted << "|" << std::setw(7)
288 << std::setprecision(2) << perSec(submitted) << "|" << std::setw(36)
289 << "" << std::endl;
290
291 log << std::left << std::setw(11) << "Accept " << "|" << std::right
292 << std::setw(7) << accepted << "|" << std::setw(7)
293 << std::setprecision(2) << perSec(accepted) << "|" << std::setw(15)
294 << std::left << "From Submit" << std::right << std::setw(7)
295 << std::setprecision(2) << fmtS(submitToAccept.percentile(0.1f))
296 << std::setw(7) << std::setprecision(2)
297 << fmtS(submitToAccept.percentile(0.5f)) << std::setw(7)
298 << std::setprecision(2) << fmtS(submitToAccept.percentile(0.9f))
299 << std::endl;
300
301 log << std::left << std::setw(11) << "Validate " << "|" << std::right
302 << std::setw(7) << validated << "|" << std::setw(7)
303 << std::setprecision(2) << perSec(validated) << "|" << std::setw(15)
304 << std::left << "From Submit" << std::right << std::setw(7)
306 << std::setw(7) << std::setprecision(2)
307 << fmtS(submitToValidate.percentile(0.5f)) << std::setw(7)
309 << std::endl;
310
311 log << std::left << std::setw(11) << "Orphan" << "|" << std::right
312 << std::setw(7) << orphaned() << "|" << std::setw(7) << "" << "|"
313 << std::setw(36) << std::endl;
314
315 log << std::left << std::setw(11) << "Unvalidated" << "|" << std::right
316 << std::setw(7) << unvalidated() << "|" << std::setw(7) << "" << "|"
317 << std::setw(43) << std::endl;
318
319 log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7)
320 << std::setfill('-') << "-" << "-" << std::setw(7)
321 << std::setfill('-') << "-" << "-" << std::setw(36)
322 << std::setfill('-') << "-" << std::endl;
323 log << std::setfill(' ');
324 }
325
326 template <class T, class Tag>
327 void
328 csv(SimDuration simDuration,
329 T& log,
330 Tag const& tag,
331 bool printHeaders = false)
332 {
333 using namespace std::chrono;
334 auto perSec = [&simDuration](std::size_t count) {
335 return double(count) / duration_cast<seconds>(simDuration).count();
336 };
337
338 auto fmtS = [](SimDuration dur) {
339 return duration_cast<duration<float>>(dur).count();
340 };
341
342 if (printHeaders)
343 {
344 log << "tag" << "," << "txNumSubmitted" << "," << "txNumAccepted"
345 << "," << "txNumValidated" << "," << "txNumOrphaned" << ","
346 << "txUnvalidated" << "," << "txRateSumbitted" << ","
347 << "txRateAccepted" << "," << "txRateValidated" << ","
348 << "txLatencySubmitToAccept10Pctl" << ","
349 << "txLatencySubmitToAccept50Pctl" << ","
350 << "txLatencySubmitToAccept90Pctl" << ","
351 << "txLatencySubmitToValidatet10Pctl" << ","
352 << "txLatencySubmitToValidatet50Pctl" << ","
353 << "txLatencySubmitToValidatet90Pctl" << std::endl;
354 }
355
356 log << tag
357 << ","
358 // txNumSubmitted
359 << submitted
360 << ","
361 // txNumAccepted
362 << accepted
363 << ","
364 // txNumValidated
365 << validated
366 << ","
367 // txNumOrphaned
368 << orphaned()
369 << ","
370 // txNumUnvalidated
371 << unvalidated()
372 << ","
373 // txRateSubmitted
374 << std::setprecision(2) << perSec(submitted)
375 << ","
376 // txRateAccepted
377 << std::setprecision(2) << perSec(accepted)
378 << ","
379 // txRateValidated
380 << std::setprecision(2) << perSec(validated)
381 << ","
382 // txLatencySubmitToAccept10Pctl
383 << std::setprecision(2) << fmtS(submitToAccept.percentile(0.1f))
384 << ","
385 // txLatencySubmitToAccept50Pctl
386 << std::setprecision(2) << fmtS(submitToAccept.percentile(0.5f))
387 << ","
388 // txLatencySubmitToAccept90Pctl
389 << std::setprecision(2) << fmtS(submitToAccept.percentile(0.9f))
390 << ","
391 // txLatencySubmitToValidate10Pctl
393 << ","
394 // txLatencySubmitToValidate50Pctl
396 << ","
397 // txLatencySubmitToValidate90Pctl
399 << "," << std::endl;
400 }
401};
402
410{
413
414 struct Tracker
415 {
418
419 Tracker(SimTime accepted_) : accepted{accepted_}
420 {
421 }
422 };
423
425
430
431 // Ignore most events by default
432 template <class E>
433 void
434 on(PeerID, SimTime, E const& e)
435 {
436 }
437
438 void
439 on(PeerID who, SimTime when, AcceptLedger const& e)
440 {
441 // First time this ledger accepted
442 if (ledgers_.emplace(e.ledger.id(), Tracker{when}).second)
443 {
444 ++accepted;
445 // ignore jumps?
446 if (e.prior.id() == e.ledger.parentID())
447 {
448 auto const it = ledgers_.find(e.ledger.parentID());
449 if (it != ledgers_.end())
450 {
451 acceptToAccept.insert(when - it->second.accepted);
452 }
453 }
454 }
455 }
456
457 void
459 {
460 // ignore jumps
461 if (e.prior.id() == e.ledger.parentID())
462 {
463 auto const it = ledgers_.find(e.ledger.id());
464 assert(it != ledgers_.end());
465 auto& tracker = it->second;
466 // first time fully validated
467 if (!tracker.fullyValidated)
468 {
470 tracker.fullyValidated = when;
471 acceptToFullyValid.insert(when - tracker.accepted);
472
473 auto const parentIt = ledgers_.find(e.ledger.parentID());
474 if (parentIt != ledgers_.end())
475 {
476 auto& parentTracker = parentIt->second;
477 if (parentTracker.fullyValidated)
478 {
480 when - *parentTracker.fullyValidated);
481 }
482 }
483 }
484 }
485 }
486
489 {
490 return std::count_if(
491 ledgers_.begin(), ledgers_.end(), [](auto const& it) {
492 return !it.second.fullyValidated;
493 });
494 }
495
496 template <class T>
497 void
498 report(SimDuration simDuration, T& log, bool printBreakline = false)
499 {
500 using namespace std::chrono;
501 auto perSec = [&simDuration](std::size_t count) {
502 return double(count) / duration_cast<seconds>(simDuration).count();
503 };
504
505 auto fmtS = [](SimDuration dur) {
506 return duration_cast<duration<float>>(dur).count();
507 };
508
509 if (printBreakline)
510 {
511 log << std::setw(11) << std::setfill('-') << "-" << "-"
512 << std::setw(7) << std::setfill('-') << "-" << "-"
513 << std::setw(7) << std::setfill('-') << "-" << "-"
514 << std::setw(36) << std::setfill('-') << "-" << std::endl;
515 log << std::setfill(' ');
516 }
517
518 log << std::left << std::setw(11) << "LedgerStats" << "|"
519 << std::setw(7) << "Count" << "|" << std::setw(7) << "Per Sec"
520 << "|" << std::setw(15) << "Latency (sec)" << std::right
521 << std::setw(7) << "10-ile" << std::setw(7) << "50-ile"
522 << std::setw(7) << "90-ile" << std::left << std::endl;
523
524 log << std::setw(11) << std::setfill('-') << "-" << "|" << std::setw(7)
525 << std::setfill('-') << "-" << "|" << std::setw(7)
526 << std::setfill('-') << "-" << "|" << std::setw(36)
527 << std::setfill('-') << "-" << std::endl;
528 log << std::setfill(' ');
529
530 log << std::left << std::setw(11) << "Accept " << "|" << std::right
531 << std::setw(7) << accepted << "|" << std::setw(7)
532 << std::setprecision(2) << perSec(accepted) << "|" << std::setw(15)
533 << std::left << "From Accept" << std::right << std::setw(7)
534 << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.1f))
535 << std::setw(7) << std::setprecision(2)
536 << fmtS(acceptToAccept.percentile(0.5f)) << std::setw(7)
537 << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.9f))
538 << std::endl;
539
540 log << std::left << std::setw(11) << "Validate " << "|" << std::right
541 << std::setw(7) << fullyValidated << "|" << std::setw(7)
542 << std::setprecision(2) << perSec(fullyValidated) << "|"
543 << std::setw(15) << std::left << "From Validate " << std::right
544 << std::setw(7) << std::setprecision(2)
545 << fmtS(fullyValidToFullyValid.percentile(0.1f)) << std::setw(7)
547 << fmtS(fullyValidToFullyValid.percentile(0.5f)) << std::setw(7)
550
551 log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7)
552 << std::setfill('-') << "-" << "-" << std::setw(7)
553 << std::setfill('-') << "-" << "-" << std::setw(36)
554 << std::setfill('-') << "-" << std::endl;
555 log << std::setfill(' ');
556 }
557
558 template <class T, class Tag>
559 void
560 csv(SimDuration simDuration,
561 T& log,
562 Tag const& tag,
563 bool printHeaders = false)
564 {
565 using namespace std::chrono;
566 auto perSec = [&simDuration](std::size_t count) {
567 return double(count) / duration_cast<seconds>(simDuration).count();
568 };
569
570 auto fmtS = [](SimDuration dur) {
571 return duration_cast<duration<float>>(dur).count();
572 };
573
574 if (printHeaders)
575 {
576 log << "tag" << "," << "ledgerNumAccepted" << ","
577 << "ledgerNumFullyValidated" << "," << "ledgerRateAccepted"
578 << "," << "ledgerRateFullyValidated" << ","
579 << "ledgerLatencyAcceptToAccept10Pctl" << ","
580 << "ledgerLatencyAcceptToAccept50Pctl" << ","
581 << "ledgerLatencyAcceptToAccept90Pctl" << ","
582 << "ledgerLatencyFullyValidToFullyValid10Pctl" << ","
583 << "ledgerLatencyFullyValidToFullyValid50Pctl" << ","
584 << "ledgerLatencyFullyValidToFullyValid90Pctl" << std::endl;
585 }
586
587 log << tag
588 << ","
589 // ledgerNumAccepted
590 << accepted
591 << ","
592 // ledgerNumFullyValidated
594 << ","
595 // ledgerRateAccepted
596 << std::setprecision(2) << perSec(accepted)
597 << ","
598 // ledgerRateFullyValidated
599 << std::setprecision(2) << perSec(fullyValidated)
600 << ","
601 // ledgerLatencyAcceptToAccept10Pctl
602 << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.1f))
603 << ","
604 // ledgerLatencyAcceptToAccept50Pctl
605 << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.5f))
606 << ","
607 // ledgerLatencyAcceptToAccept90Pctl
608 << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.9f))
609 << ","
610 // ledgerLatencyFullyValidToFullyValid10Pctl
613 << ","
614 // ledgerLatencyFullyValidToFullyValid50Pctl
617 << ","
618 // ledgerLatencyFullyValidToFullyValid90Pctl
621 }
622};
623
630{
632
633 // Ignore most events by default
634 template <class E>
635 void
636 on(PeerID, SimTime, E const& e)
637 {
638 }
639
640 void
641 on(PeerID who, SimTime when, AcceptLedger const& e)
642 {
643 out << when.time_since_epoch().count() << ": Node " << who
644 << " accepted " << "L" << e.ledger.id() << " " << e.ledger.txs()
645 << "\n";
646 }
647
648 void
650 {
651 out << when.time_since_epoch().count() << ": Node " << who
652 << " fully-validated " << "L" << e.ledger.id() << " "
653 << e.ledger.txs() << "\n";
654 }
655};
656
663{
671
674
675 // Ignore most events by default
676 template <class E>
677 void
678 on(PeerID, SimTime, E const& e)
679 {
680 }
681
682 void
683 on(PeerID who, SimTime when, AcceptLedger const& e)
684 {
685 // Not a direct child -> parent switch
686 if (e.ledger.parentID() != e.prior.id())
687 closeJumps.emplace_back(Jump{who, when, e.prior, e.ledger});
688 }
689
690 void
692 {
693 // Not a direct child -> parent switch
694 if (e.ledger.parentID() != e.prior.id())
695 fullyValidatedJumps.emplace_back(
696 Jump{who, when, e.prior, e.ledger});
697 }
698};
699
700} // namespace csf
701} // namespace test
702} // namespace ripple
703
704#endif
Group of collectors.
Definition collectors.h:37
static void apply(std::tuple< Cs &... > &cs, PeerID who, SimTime when, E e, std::index_sequence< Is... >)
Definition collectors.h:49
std::tuple< Cs &... > cs
Definition collectors.h:38
static void apply(C &c, PeerID who, SimTime when, E e)
Definition collectors.h:42
void on(PeerID who, SimTime when, E e)
Definition collectors.h:70
Collectors(Cs &... cs_)
Constructor.
Definition collectors.h:64
void insert(T const &s)
Insert an sample.
Definition Histogram.h:36
T percentile(float p) const
Calculate the given percentile of the distribution.
Definition Histogram.h:93
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition ledgers.h:45
TxSetType const & txs() const
Definition ledgers.h:195
A single transaction.
Definition Tx.h:23
ID const & id() const
Definition Tx.h:37
T count_if(T... args)
T endl(T... args)
T is_same_v
T left(T... args)
typename SimClock::duration SimDuration
Definition SimTime.h:17
typename SimClock::time_point SimTime
Definition SimTime.h:18
Collectors< Cs... > makeCollectors(Cs &... cs)
Create an instance of Collectors<Cs...>
Definition collectors.h:79
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
STL namespace.
T setfill(T... args)
T setprecision(T... args)
T setw(T... args)
Peer accepted consensus results.
Definition events.h:102
Maintain an instance of a Collector per peer.
Definition collectors.h:94
CollectorType const & operator[](PeerID who) const
Definition collectors.h:104
void on(PeerID who, SimTime when, E const &e)
Definition collectors.h:110
std::map< PeerID, CollectorType > byNode
Definition collectors.h:95
CollectorType & operator[](PeerID who)
Definition collectors.h:98
Peer fully validated a new ledger.
Definition events.h:121
Ledger prior
The prior fully validated ledger This is a jump if prior.id() != ledger.parentID()
Definition events.h:127
Ledger ledger
The new fully validated ledger.
Definition events.h:123
Saves information about Jumps for closed and fully validated ledgers.
Definition collectors.h:663
std::vector< Jump > fullyValidatedJumps
Definition collectors.h:673
void on(PeerID who, SimTime when, AcceptLedger const &e)
Definition collectors.h:683
void on(PeerID, SimTime, E const &e)
Definition collectors.h:678
void on(PeerID who, SimTime when, FullyValidateLedger const &e)
Definition collectors.h:691
std::vector< Jump > closeJumps
Definition collectors.h:672
std::optional< SimTime > fullyValidated
Definition collectors.h:417
Tracks the accepted -> validated evolution of ledgers.
Definition collectors.h:410
void on(PeerID, SimTime, E const &e)
Definition collectors.h:434
void on(PeerID who, SimTime when, AcceptLedger const &e)
Definition collectors.h:439
std::size_t unvalidated() const
Definition collectors.h:488
hash_map< Ledger::ID, Tracker > ledgers_
Definition collectors.h:424
void report(SimDuration simDuration, T &log, bool printBreakline=false)
Definition collectors.h:498
void csv(SimDuration simDuration, T &log, Tag const &tag, bool printHeaders=false)
Definition collectors.h:560
void on(PeerID who, SimTime when, FullyValidateLedger const &e)
Definition collectors.h:458
Collector which ignores all events.
Definition collectors.h:118
void on(PeerID, SimTime, E const &e)
Definition collectors.h:121
Tracks the overall duration of a simulation.
Definition collectors.h:128
void on(PeerID, SimTime when, E const &e)
Definition collectors.h:135
Write out stream of ledger activity.
Definition collectors.h:630
void on(PeerID who, SimTime when, AcceptLedger const &e)
Definition collectors.h:641
void on(PeerID, SimTime, E const &e)
Definition collectors.h:636
void on(PeerID who, SimTime when, FullyValidateLedger const &e)
Definition collectors.h:649
A transaction submitted to a peer.
Definition events.h:73
Tx tx
The submitted transaction.
Definition events.h:75
std::optional< SimTime > accepted
Definition collectors.h:167
std::optional< SimTime > validated
Definition collectors.h:168
Tracker(Tx tx_, SimTime submitted_)
Definition collectors.h:170
Tracks the submission -> accepted -> validated evolution of transactions.
Definition collectors.h:157
std::size_t orphaned() const
Definition collectors.h:236
hash_map< Tx::ID, Tracker > txs
Definition collectors.h:175
void on(PeerID who, SimTime when, SubmitTx const &e)
Definition collectors.h:189
void csv(SimDuration simDuration, T &log, Tag const &tag, bool printHeaders=false)
Definition collectors.h:328
std::size_t unvalidated() const
Definition collectors.h:245
void report(SimDuration simDuration, T &log, bool printBreakline=false)
Definition collectors.h:254
void on(PeerID, SimTime when, E const &e)
Definition collectors.h:184
void on(PeerID who, SimTime when, FullyValidateLedger const &e)
Definition collectors.h:216
void on(PeerID who, SimTime when, AcceptLedger const &e)
Definition collectors.h:199