-
Notifications
You must be signed in to change notification settings - Fork 138
/
Copy pathConcurrentGCStats.hpp
272 lines (233 loc) · 11.3 KB
/
ConcurrentGCStats.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*******************************************************************************
* Copyright IBM Corp. and others 1991
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#if !defined(CONCURRENTGCSTATS_HPP_)
#define CONCURRENTGCSTATS_HPP_
#include "omrcomp.h"
#include "omrport.h"
#include "modronbase.h"
#include "omr.h"
#include "AtomicOperations.hpp"
#include "Base.hpp"
class MM_EnvironmentBase;
/**
* @todo Provide class documentation
* @ingroup GC_Stats
*/
class MM_ConcurrentGCStats : public MM_Base
{
volatile uintptr_t _executionMode;
uintptr_t _executionModeAtGC;
uintptr_t _initWorkRequired;
uintptr_t _traceSizeTarget;
uintptr_t _kickoffThreshold;
uintptr_t _cardCleaningThreshold;
uintptr_t _remainingFree;
uintptr_t _allocationsTaxed;
uintptr_t _allocationsTaxedAt0;
uintptr_t _allocationsTaxedAt25;
uintptr_t _allocationsTaxedAt50;
uintptr_t _allocationsTaxedAt75;
uintptr_t _allocationsTaxedAt100;
/* The following statistics are reset at the end of every concurrent cycle */
volatile uintptr_t _traceSizeCount;
volatile uintptr_t _cardCleanCount;
volatile uintptr_t _conHelperTraceSizeCount;
volatile uintptr_t _conHelperCardCleanCount;
volatile uintptr_t _completeTracingCount;
volatile uintptr_t _finalTraceCount;
volatile uintptr_t _finalCardCleanCount;
volatile uintptr_t _RSScanTraceCount;
volatile uintptr_t _RSObjectsFound;
volatile uintptr_t _threadsScannedCount;
uintptr_t _threadsToScanCount;
bool _concurrentWorkStackOverflowOcurred;
uintptr_t _concurrentWorkStackOverflowCount;
volatile uint32_t _completedModes; /**< a bit mask of modes which have been completed in the current cycle */
ConcurrentKickoffReason _kickoffReason; /**< a constant indicating why kickoff occured */
ConcurrentCardCleaningReason _cardCleaningReason; /**< a constant indicating why card cleaning was kicked off */
public:
static const char* getConcurrentStatusString(MM_EnvironmentBase *env, uintptr_t status, char *statusBuffer, uintptr_t statusBufferLength);
MMINLINE uintptr_t getExecutionMode() { return _executionMode; };
MMINLINE bool concurrentMarkNotStarted() { return (_executionMode == CONCURRENT_OFF); }
MMINLINE bool concurrentMarkInProgress() { return (_executionMode > CONCURRENT_OFF); }
MMINLINE bool switchExecutionMode(uintptr_t oldMode, uintptr_t newMode)
{
return oldMode == MM_AtomicOperations::lockCompareExchange(&_executionMode, oldMode, newMode);
}
MMINLINE uintptr_t getExecutionModeAtGC() { return _executionModeAtGC; };
MMINLINE void setExecutionModeAtGC(uintptr_t executionMode) { _executionModeAtGC = executionMode; };
/* Getter and setter methods for concurrent statistics */
MMINLINE uintptr_t getKickoffThreshold() { return _kickoffThreshold; };
MMINLINE void setKickoffThreshold(uintptr_t threshold ){ _kickoffThreshold= threshold; };
MMINLINE ConcurrentKickoffReason getKickoffReason() { return _kickoffReason; }
MMINLINE void clearKickoffReason(){ _kickoffReason = NO_KICKOFF_REASON; }
MMINLINE void setKickoffReason(ConcurrentKickoffReason reason)
{
if (NO_KICKOFF_REASON == _kickoffReason) {
_kickoffReason = reason;
}
}
MMINLINE uintptr_t getInitWorkRequired() { return _initWorkRequired; };
MMINLINE void setInitWorkRequired(uintptr_t required ) { _initWorkRequired = required; };
MMINLINE uintptr_t getTraceSizeTarget() { return _traceSizeTarget; };
MMINLINE void setTraceSizeTarget(uintptr_t target ){ _traceSizeTarget = target; };
MMINLINE void setRemainingFree(uintptr_t free) { _remainingFree = free; };
MMINLINE uintptr_t getRemainingFree() { return _remainingFree; };
MMINLINE void clearAllocationTaxCounts()
{
_allocationsTaxed = 0;
_allocationsTaxedAt0 = 0;
_allocationsTaxedAt25 = 0;
_allocationsTaxedAt50 = 0;
_allocationsTaxedAt75 = 0;
_allocationsTaxedAt100 = 0;
}
MMINLINE void analyzeAllocationTax(uintptr_t taxDue, uintptr_t taxPaid)
{
_allocationsTaxed++;
if (taxPaid == 0) {
_allocationsTaxedAt0++;
} else if (taxPaid <= (uintptr_t)((double)taxDue * 0.25)) {
_allocationsTaxedAt25++;
} else if (taxPaid <= (uintptr_t)((double)taxDue * 0.5)) {
_allocationsTaxedAt50++;
} else if (taxPaid <= (uintptr_t)((double)taxDue * 0.75)) {
_allocationsTaxedAt75++;
} else {
_allocationsTaxedAt100++;
}
}
MMINLINE void printAllocationTaxReport(OMR_VM *omrVM)
{
OMRPORT_ACCESS_FROM_OMRVM(omrVM);
omrtty_printf("Concurrent mark analysis: Total Allocations: %zu Tax Paid 0%%: %zu 25%%: %zu 50%%: %zu 75%%: %zu 100%%+: %zu\n",
_allocationsTaxed,
_allocationsTaxedAt0,
_allocationsTaxedAt25,
_allocationsTaxedAt50,
_allocationsTaxedAt75,
_allocationsTaxedAt100
);
}
MMINLINE uintptr_t getTraceSizeCount() { return (uintptr_t) _traceSizeCount; };
MMINLINE uintptr_t getCardCleanCount() { return (uintptr_t) _cardCleanCount; };
MMINLINE uintptr_t getConHelperTraceSizeCount() { return (uintptr_t) _conHelperTraceSizeCount; };
MMINLINE uintptr_t getConHelperCardCleanCount() { return (uintptr_t) _conHelperCardCleanCount; };
MMINLINE uintptr_t getFinalTraceCount() { return (uintptr_t) _finalTraceCount; };
MMINLINE uintptr_t getCompleteTracingCount(){ return (uintptr_t) _completeTracingCount; };
MMINLINE uintptr_t getFinalCardCleanCount() { return (uintptr_t) _finalCardCleanCount; };
MMINLINE uintptr_t getRSScanTraceCount() { return (uintptr_t) _RSScanTraceCount; };
MMINLINE uintptr_t getRSObjectsFound(){ return (uintptr_t) _RSObjectsFound; };
MMINLINE uintptr_t getCardCleaningThreshold() { return _cardCleaningThreshold; };
MMINLINE void setCardCleaningThreshold(uintptr_t threshold) { _cardCleaningThreshold= threshold; };
MMINLINE uintptr_t getTotalTraced() { return _conHelperTraceSizeCount + _conHelperCardCleanCount + _traceSizeCount + _cardCleanCount; };
MMINLINE uintptr_t getMutatorsTraced() { return _traceSizeCount + _cardCleanCount; };
MMINLINE uintptr_t getConHelperTraced() { return _conHelperTraceSizeCount + _conHelperCardCleanCount; };
MMINLINE bool getConcurrentWorkStackOverflowOcurred() { return _concurrentWorkStackOverflowOcurred; };
MMINLINE void setConcurrentWorkStackOverflowOcurred(bool overflow){ _concurrentWorkStackOverflowOcurred = overflow; };
MMINLINE uintptr_t getConcurrentWorkStackOverflowCount() { return _concurrentWorkStackOverflowCount; };
/* Functions required to perform atomic updates of concurrent statistics */
MMINLINE void incrementCount(uintptr_t *count, uintptr_t increment)
{
MM_AtomicOperations::add(count, increment);
};
MMINLINE void clearCount(uintptr_t *count)
{
MM_AtomicOperations::set(count, 0);
};
MMINLINE void incTraceSizeCount(uintptr_t increment) { incrementCount((uintptr_t *)&_traceSizeCount, increment); };
MMINLINE void incConHelperTraceSizeCount(uintptr_t increment) { incrementCount((uintptr_t *)&_conHelperTraceSizeCount, increment); };
MMINLINE void incCardCleanCount(uintptr_t increment){ incrementCount((uintptr_t *)&_cardCleanCount, increment); };
MMINLINE void incConHelperCardCleanCount(uintptr_t increment){ incrementCount((uintptr_t *)&_conHelperCardCleanCount,increment); };
MMINLINE void incCompleteTracingCount(uintptr_t increment) { incrementCount((uintptr_t *)&_completeTracingCount, increment); };
MMINLINE void incFinalTraceCount(uintptr_t increment) { incrementCount((uintptr_t *)&_finalTraceCount, increment); };
MMINLINE void incFinalCardCleanCount(uintptr_t increment){ incrementCount((uintptr_t *)&_finalCardCleanCount, increment); };
MMINLINE void incRSScanTraceCount(uintptr_t increment) { incrementCount((uintptr_t *)&_RSScanTraceCount, increment); };
MMINLINE void incRSObjectsFound(uintptr_t increment) { incrementCount((uintptr_t *)&_RSObjectsFound, increment); };
MMINLINE void incConcurrentWorkStackOverflowCount() { incrementCount((uintptr_t *)&_concurrentWorkStackOverflowCount, 1); };
MMINLINE void setThreadsToScanCount(uintptr_t count) { _threadsToScanCount = count; };
MMINLINE uintptr_t getThreadsToScanCount() { return _threadsToScanCount; };
MMINLINE void incThreadsScannedCount() { incrementCount((uintptr_t*)&_threadsScannedCount, 1); };
MMINLINE uintptr_t getThreadsScannedCount() { return _threadsScannedCount; };
MMINLINE bool isRootTracingComplete() { return (_completedModes & CONCURRENT_ROOT_TRACING) == CONCURRENT_ROOT_TRACING; };
MMINLINE void setModeComplete(ConcurrentStatus mode) {
uint32_t mask = (uint32_t)1 << mode;
uint32_t currentValue = _completedModes;
do {
currentValue = MM_AtomicOperations::lockCompareExchangeU32(&_completedModes, currentValue, currentValue | mask);
} while ( (currentValue & mask) != mask);
}
MMINLINE void setCardCleaningReason(ConcurrentCardCleaningReason reason) { _cardCleaningReason = reason; };
MMINLINE ConcurrentCardCleaningReason getCardCleaningReason() { return _cardCleaningReason; };
MMINLINE void reset()
{
clearCount((uintptr_t *)&_traceSizeCount);
clearCount((uintptr_t *)&_conHelperTraceSizeCount);
clearCount((uintptr_t *)&_cardCleanCount);
clearCount((uintptr_t *)&_conHelperCardCleanCount);
clearCount((uintptr_t *)&_completeTracingCount);
clearCount((uintptr_t *)&_finalTraceCount);
clearCount((uintptr_t *)&_finalCardCleanCount);
clearCount((uintptr_t *)&_RSScanTraceCount);
clearCount((uintptr_t *)&_RSObjectsFound);
clearCount((uintptr_t *)&_threadsScannedCount);
clearCount(&_threadsToScanCount);
_completedModes = 0;
_cardCleaningReason = CARD_CLEANING_REASON_NONE;
};
/**
* Create a ConcurrentGCStats object.
*/
MM_ConcurrentGCStats() :
MM_Base(),
_executionMode((uintptr_t)CONCURRENT_OFF),
_executionModeAtGC(CONCURRENT_OFF),
_initWorkRequired(0),
_traceSizeTarget(0),
_kickoffThreshold(0),
_cardCleaningThreshold(0),
_remainingFree(0),
_allocationsTaxed(0),
_allocationsTaxedAt0(0),
_allocationsTaxedAt25(0),
_allocationsTaxedAt50(0),
_allocationsTaxedAt75(0),
_allocationsTaxedAt100(0),
_traceSizeCount(0),
_cardCleanCount(0),
_conHelperTraceSizeCount(0),
_conHelperCardCleanCount(0),
_completeTracingCount(0),
_finalTraceCount(0),
_finalCardCleanCount(0),
_RSScanTraceCount(0),
_RSObjectsFound(0),
_threadsScannedCount(0),
_threadsToScanCount(0),
_concurrentWorkStackOverflowOcurred(false),
_concurrentWorkStackOverflowCount(0),
_completedModes(0),
_kickoffReason(NO_KICKOFF_REASON),
_cardCleaningReason(CARD_CLEANING_REASON_NONE)
{}
};
#endif /* CONCURRENTGCSTATS_HPP_ */