rippled
Loading...
Searching...
No Matches
LoadMonitor.cpp
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#include <xrpld/core/LoadMonitor.h>
21#include <xrpl/basics/Log.h>
22#include <xrpl/basics/UptimeClock.h>
23
24namespace ripple {
25
26/*
27
28TODO
29----
30
31- Use Journal for logging
32
33*/
34
35//------------------------------------------------------------------------------
36
38 : count(0), latencyAvg(0), latencyPeak(0), isOverloaded(false)
39{
40}
41
42//------------------------------------------------------------------------------
43
45 : mCounts(0)
47 , mLatencyMSAvg(0)
51 , mLastUpdate(UptimeClock::now())
52 , j_(j)
53{
54}
55
56// VFALCO NOTE WHY do we need "the mutex?" This dependence on
57// a hidden global, especially a synchronization primitive,
58// is a flawed design.
59// It's not clear exactly which data needs to be protected.
60//
61// call with the mutex
62void
64{
65 using namespace std::chrono_literals;
66 auto now = UptimeClock::now();
67 if (now == mLastUpdate) // current
68 return;
69
70 // VFALCO TODO Why 8?
71 if ((now < mLastUpdate) || (now > (mLastUpdate + 8s)))
72 {
73 // way out of date
74 mCounts = 0;
76 mLatencyMSAvg = 0ms;
77 mLatencyMSPeak = 0ms;
78 mLastUpdate = now;
79 return;
80 }
81
82 // do exponential decay
83 /*
84 David:
85
86 "Imagine if you add 10 to something every second. And you
87 also reduce it by 1/4 every second. It will "idle" at 40,
88 correponding to 10 counts per second."
89 */
90 do
91 {
92 mLastUpdate += 1s;
93 mCounts -= ((mCounts + 3) / 4);
94 mLatencyEvents -= ((mLatencyEvents + 3) / 4);
97 } while (mLastUpdate < now);
98}
99
100void
102{
103 using namespace std::chrono;
104
105 auto const total = s.runTime() + s.waitTime();
106 // Don't include "jitter" as part of the latency
107 auto const latency = total < 2ms ? 0ms : round<milliseconds>(total);
108
109 if (latency > 500ms)
110 {
111 auto mj = (latency > 1s) ? j_.warn() : j_.info();
112 JLOG(mj) << "Job: " << s.name()
113 << " run: " << round<milliseconds>(s.runTime()).count() << "ms"
114 << " wait: " << round<milliseconds>(s.waitTime()).count()
115 << "ms";
116 }
117
118 addSamples(1, latency);
119}
120
121/* Add multiple samples
122 @param count The number of samples to add
123 @param latencyMS The total number of milliseconds
124*/
125void
127{
129
130 update();
131 mCounts += count;
132 mLatencyEvents += count;
133 mLatencyMSAvg += latency;
134 mLatencyMSPeak += latency;
135
136 auto const latencyPeak = mLatencyEvents * latency * 4 / count;
137
138 if (mLatencyMSPeak < latencyPeak)
139 mLatencyMSPeak = latencyPeak;
140}
141
142void
146{
147 mTargetLatencyAvg = avg;
148 mTargetLatencyPk = pk;
149}
150
151bool
155{
156 using namespace std::chrono_literals;
157 return (mTargetLatencyPk > 0ms && (peak > mTargetLatencyPk)) ||
158 (mTargetLatencyAvg > 0ms && (avg > mTargetLatencyAvg));
159}
160
161bool
163{
165
166 update();
167
168 if (mLatencyEvents == 0)
169 return 0;
170
171 return isOverTarget(
174}
175
178{
179 using namespace std::chrono_literals;
180 Stats stats;
181
183
184 update();
185
186 stats.count = mCounts / 4;
187
188 if (mLatencyEvents == 0)
189 {
190 stats.latencyAvg = 0ms;
191 stats.latencyPeak = 0ms;
192 }
193 else
194 {
197 }
198
199 stats.isOverloaded = isOverTarget(stats.latencyAvg, stats.latencyPeak);
200
201 return stats;
202}
203
204} // namespace ripple
A generic endpoint for log messages.
Definition: Journal.h:59
Stream info() const
Definition: Journal.h:323
Stream warn() const
Definition: Journal.h:329
std::string const & name() const
Definition: LoadEvent.cpp:47
std::chrono::steady_clock::duration waitTime() const
Definition: LoadEvent.cpp:53
std::chrono::steady_clock::duration runTime() const
Definition: LoadEvent.cpp:59
LoadMonitor(beast::Journal j)
Definition: LoadMonitor.cpp:44
void setTargetLatency(std::chrono::milliseconds avg, std::chrono::milliseconds pk)
void addSamples(int count, std::chrono::milliseconds latency)
std::chrono::milliseconds mLatencyMSAvg
Definition: LoadMonitor.h:80
std::uint64_t mCounts
Definition: LoadMonitor.h:78
void addLoadSample(LoadEvent const &sample)
beast::Journal const j_
Definition: LoadMonitor.h:85
std::chrono::milliseconds mTargetLatencyAvg
Definition: LoadMonitor.h:82
std::chrono::milliseconds mLatencyMSPeak
Definition: LoadMonitor.h:81
std::mutex mutex_
Definition: LoadMonitor.h:76
bool isOverTarget(std::chrono::milliseconds avg, std::chrono::milliseconds peak)
std::chrono::milliseconds mTargetLatencyPk
Definition: LoadMonitor.h:83
UptimeClock::time_point mLastUpdate
Definition: LoadMonitor.h:84
Tracks program uptime to seconds precision.
Definition: UptimeClock.h:38
static time_point now()
Definition: UptimeClock.cpp:63
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::chrono::milliseconds latencyAvg
Definition: LoadMonitor.h:61
std::chrono::milliseconds latencyPeak
Definition: LoadMonitor.h:62