/
ClientStatistics.java
224 lines (192 loc) · 9.22 KB
/
ClientStatistics.java
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
package org.infinispan.client.hotrod.impl;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import org.infinispan.client.hotrod.jmx.RemoteCacheClientStatisticsMXBean;
import org.infinispan.client.hotrod.near.NearCacheService;
import org.infinispan.commons.time.TimeService;
import org.infinispan.commons.util.concurrent.StripedCounters;
public final class ClientStatistics implements RemoteCacheClientStatisticsMXBean {
private final boolean enabled;
private final AtomicLong startNanoseconds = new AtomicLong(0);
private final AtomicLong resetNanoseconds = new AtomicLong(0);
private final NearCacheService nearCacheService;
private final TimeService timeService;
private final StripedCounters<StripeB> counters = new StripedCounters<>(StripeC::new);
ClientStatistics(boolean enabled, TimeService timeService, NearCacheService nearCacheService) {
this.enabled = enabled;
this.timeService = timeService;
this.nearCacheService = nearCacheService;
if (nearCacheService != null)
nearCacheService.setInvalidationCallback(this::incrementNearCacheInvalidations);
}
ClientStatistics(boolean enabled, TimeService timeService) {
this(enabled, timeService, null);
}
public boolean isEnabled() {
return enabled;
}
@Override
public long getRemoteHits() {
return counters.get(StripeB.remoteCacheHitsFieldUpdater);
}
@Override
public long getRemoteMisses() {
return counters.get(StripeB.remoteCacheMissesFieldUpdater);
}
@Override
public long getAverageRemoteReadTime() {
long total = counters.get(StripeB.remoteCacheHitsFieldUpdater) + counters.get(StripeB.remoteCacheMissesFieldUpdater);
if (total == 0)
return 0;
total = (counters.get(StripeB.remoteCacheHitsTimeFieldUpdater) + counters.get(StripeB.remoteCacheMissesTimeFieldUpdater)) / total;
return TimeUnit.NANOSECONDS.toMillis(total);
}
@Override
public long getRemoteStores() {
return counters.get(StripeB.remoteCacheStoresFieldUpdater);
}
@Override
public long getAverageRemoteStoreTime() {
long total = counters.get(StripeB.remoteCacheStoresFieldUpdater);
if (total == 0)
return 0;
total = counters.get(StripeB.remoteCacheStoresTimeFieldUpdater) / total;
return TimeUnit.NANOSECONDS.toMillis(total);
}
@Override
public long getRemoteRemoves() {
return counters.get(StripeB.remoteCacheRemovesFieldUpdater);
}
@Override
public long getAverageRemoteRemovesTime() {
long total = counters.get(StripeB.remoteCacheRemovesFieldUpdater);
if (total == 0)
return 0;
total = counters.get(StripeB.remoteCacheRemovesTimeFieldUpdater) / total;
return TimeUnit.NANOSECONDS.toMillis(total);
}
@Override
public long getNearCacheHits() {
return counters.get(StripeB.nearCacheHitsFieldUpdater);
}
@Override
public long getNearCacheMisses() {
return counters.get(StripeB.nearCacheMissesFieldUpdater);
}
@Override
public long getNearCacheInvalidations() {
return counters.get(StripeB.nearCacheInvalidationsFieldUpdater);
}
@Override
public long getNearCacheSize() {
return nearCacheService != null ? nearCacheService.size() : 0;
}
public long time() {
return timeService.time();
}
public void dataRead(boolean foundValue, long startTimeNanoSeconds, int count) {
long duration = timeService.timeDuration(startTimeNanoSeconds, TimeUnit.NANOSECONDS);
StripeB stripe = counters.stripeForCurrentThread();
if (foundValue) {
counters.add(StripeB.remoteCacheHitsTimeFieldUpdater, stripe, duration);
counters.add(StripeB.remoteCacheHitsFieldUpdater, stripe, count);
} else {
counters.add(StripeB.remoteCacheMissesTimeFieldUpdater, stripe, duration);
counters.add(StripeB.remoteCacheMissesFieldUpdater, stripe, count);
}
}
public void dataStore(long startTimeNanoSeconds, int count) {
long duration = timeService.timeDuration(startTimeNanoSeconds, TimeUnit.NANOSECONDS);
StripeB stripe = counters.stripeForCurrentThread();
counters.add(StripeB.remoteCacheStoresTimeFieldUpdater, stripe, duration);
counters.add(StripeB.remoteCacheStoresFieldUpdater, stripe, count);
}
public void dataRemove(long startTimeNanoSeconds, int count) {
long duration = timeService.timeDuration(startTimeNanoSeconds, TimeUnit.NANOSECONDS);
StripeB stripe = counters.stripeForCurrentThread();
counters.add(StripeB.remoteCacheRemovesTimeFieldUpdater, stripe, duration);
counters.add(StripeB.remoteCacheRemovesFieldUpdater, stripe, count);
}
public void incrementNearCacheMisses() {
counters.increment(StripeB.nearCacheMissesFieldUpdater, counters.stripeForCurrentThread());
}
public void incrementNearCacheHits() {
counters.increment(StripeB.nearCacheHitsFieldUpdater, counters.stripeForCurrentThread());
}
public void incrementNearCacheInvalidations() {
counters.increment(StripeB.nearCacheInvalidationsFieldUpdater, counters.stripeForCurrentThread());
}
@Override
public void resetStatistics() {
counters.reset(StripeB.remoteCacheHitsFieldUpdater);
counters.reset(StripeB.remoteCacheHitsTimeFieldUpdater);
counters.reset(StripeB.remoteCacheMissesFieldUpdater);
counters.reset(StripeB.remoteCacheMissesTimeFieldUpdater);
counters.reset(StripeB.remoteCacheRemovesFieldUpdater);
counters.reset(StripeB.remoteCacheRemovesTimeFieldUpdater);
counters.reset(StripeB.remoteCacheStoresFieldUpdater);
counters.reset(StripeB.remoteCacheStoresTimeFieldUpdater);
counters.reset(StripeB.nearCacheHitsFieldUpdater);
counters.reset(StripeB.nearCacheMissesFieldUpdater);
counters.reset(StripeB.nearCacheInvalidationsFieldUpdater);
startNanoseconds.set(timeService.time());
resetNanoseconds.set(startNanoseconds.get());
}
@Override
public long getTimeSinceReset() {
return timeService.timeDuration(resetNanoseconds.get(), TimeUnit.SECONDS);
}
/**
* It returns a {@link ClientStatistics} instance to be used when the statistics aren't needed.
*
* @return a disabled {@link ClientStatistics} instance.
*/
public static ClientStatistics dummyClientStatistics(TimeService timeService) {
return new ClientStatistics(false, timeService);
}
private static class StripeA {
@SuppressWarnings("unused")
private long slack1, slack2, slack3, slack4, slack5, slack6, slack7, slack8;
}
@SuppressWarnings("VolatileLongOrDoubleField")
private static class StripeB extends StripeA {
static final AtomicLongFieldUpdater<StripeB> remoteCacheHitsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheHits");
static final AtomicLongFieldUpdater<StripeB> remoteCacheHitsTimeFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheHitsTime");
static final AtomicLongFieldUpdater<StripeB> remoteCacheMissesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheMisses");
static final AtomicLongFieldUpdater<StripeB> remoteCacheMissesTimeFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheMissesTime");
static final AtomicLongFieldUpdater<StripeB> remoteCacheRemovesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheRemoves");
static final AtomicLongFieldUpdater<StripeB> remoteCacheRemovesTimeFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheRemovesTime");
static final AtomicLongFieldUpdater<StripeB> remoteCacheStoresFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheStores");
static final AtomicLongFieldUpdater<StripeB> remoteCacheStoresTimeFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "remoteCacheStoresTime");
static final AtomicLongFieldUpdater<StripeB> nearCacheHitsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "nearCacheHits");
static final AtomicLongFieldUpdater<StripeB> nearCacheMissesFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "nearCacheMisses");
static final AtomicLongFieldUpdater<StripeB> nearCacheInvalidationsFieldUpdater =
AtomicLongFieldUpdater.newUpdater(StripeB.class, "nearCacheInvalidations");
private volatile long remoteCacheHits = 0;
private volatile long remoteCacheHitsTime = 0;
private volatile long remoteCacheMisses = 0;
private volatile long remoteCacheMissesTime = 0;
private volatile long remoteCacheRemoves = 0;
private volatile long remoteCacheRemovesTime = 0;
private volatile long remoteCacheStores = 0;
private volatile long remoteCacheStoresTime = 0;
private volatile long nearCacheHits = 0;
private volatile long nearCacheMisses = 0;
private volatile long nearCacheInvalidations = 0;
}
private static final class StripeC extends StripeB {
@SuppressWarnings("unused")
private long slack1, slack2, slack3, slack4, slack5, slack6, slack7, slack8;
}
}