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