1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.io.hfile;
20
21 import java.util.concurrent.atomic.AtomicLong;
22
23 import org.apache.hadoop.hbase.classification.InterfaceAudience;
24
25 import com.yammer.metrics.core.Histogram;
26 import com.yammer.metrics.core.MetricsRegistry;
27
28
29
30
31 @InterfaceAudience.Private
32 public class CacheStats {
33
34
35
36 private static final MetricsRegistry METRICS = new MetricsRegistry();
37
38
39
40
41 static final int DEFAULT_WINDOW_PERIODS = 5;
42
43
44 private final AtomicLong hitCount = new AtomicLong(0);
45
46
47 private final AtomicLong primaryHitCount = new AtomicLong(0);
48
49
50
51
52
53
54
55 private final AtomicLong hitCachingCount = new AtomicLong(0);
56
57
58 private final AtomicLong missCount = new AtomicLong(0);
59
60
61 private final AtomicLong primaryMissCount = new AtomicLong(0);
62
63
64
65
66 private final AtomicLong missCachingCount = new AtomicLong(0);
67
68
69 private final AtomicLong evictionCount = new AtomicLong(0);
70
71
72 private final AtomicLong evictedBlockCount = new AtomicLong(0);
73
74
75 private final AtomicLong primaryEvictedBlockCount = new AtomicLong(0);
76
77
78 private final AtomicLong failedInserts = new AtomicLong(0);
79
80
81 private final int numPeriodsInWindow;
82
83 private final long [] hitCounts;
84
85 private final long [] hitCachingCounts;
86
87 private final long [] requestCounts;
88
89 private final long [] requestCachingCounts;
90
91 private long lastHitCount = 0;
92
93 private long lastHitCachingCount = 0;
94
95 private long lastRequestCount = 0;
96
97 private long lastRequestCachingCount = 0;
98
99 private int windowIndex = 0;
100
101
102
103 private Histogram ageAtEviction;
104 private long startTime = System.nanoTime();
105
106 public CacheStats(final String name) {
107 this(name, DEFAULT_WINDOW_PERIODS);
108 }
109
110 public CacheStats(final String name, int numPeriodsInWindow) {
111 this.numPeriodsInWindow = numPeriodsInWindow;
112 this.hitCounts = initializeZeros(numPeriodsInWindow);
113 this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
114 this.requestCounts = initializeZeros(numPeriodsInWindow);
115 this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
116 this.ageAtEviction = METRICS.newHistogram(CacheStats.class, name + ".ageAtEviction");
117 }
118
119 @Override
120 public String toString() {
121 AgeSnapshot snapshot = getAgeAtEvictionSnapshot();
122 return "hitCount=" + getHitCount() + ", hitCachingCount=" + getHitCachingCount() +
123 ", missCount=" + getMissCount() + ", missCachingCount=" + getMissCachingCount() +
124 ", evictionCount=" + getEvictionCount() +
125 ", evictedBlockCount=" + getEvictedCount() +
126 ", primaryMissCount=" + getPrimaryMissCount() +
127 ", primaryHitCount=" + getPrimaryHitCount() +
128 ", evictedAgeMean=" + snapshot.getMean() +
129 ", evictedAgeStdDev=" + snapshot.getStdDev();
130 }
131
132 public void miss(boolean caching, boolean primary) {
133 missCount.incrementAndGet();
134 if (primary) primaryMissCount.incrementAndGet();
135 if (caching) missCachingCount.incrementAndGet();
136 }
137
138 public void hit(boolean caching) {
139 hit(caching, true);
140 }
141
142 public void hit(boolean caching, boolean primary) {
143 hitCount.incrementAndGet();
144 if (primary) primaryHitCount.incrementAndGet();
145 if (caching) hitCachingCount.incrementAndGet();
146 }
147
148 public void evict() {
149 evictionCount.incrementAndGet();
150 }
151
152 public void evicted(final long t, boolean primary) {
153 if (t > this.startTime) this.ageAtEviction.update(t - this.startTime);
154 this.evictedBlockCount.incrementAndGet();
155 if (primary) {
156 primaryEvictedBlockCount.incrementAndGet();
157 }
158 }
159
160 public long failInsert() {
161 return failedInserts.incrementAndGet();
162 }
163
164 public long getRequestCount() {
165 return getHitCount() + getMissCount();
166 }
167
168 public long getRequestCachingCount() {
169 return getHitCachingCount() + getMissCachingCount();
170 }
171
172 public long getMissCount() {
173 return missCount.get();
174 }
175
176 public long getPrimaryMissCount() {
177 return primaryMissCount.get();
178 }
179
180 public long getMissCachingCount() {
181 return missCachingCount.get();
182 }
183
184 public long getHitCount() {
185 return hitCount.get();
186 }
187
188 public long getPrimaryHitCount() {
189 return primaryHitCount.get();
190 }
191
192 public long getHitCachingCount() {
193 return hitCachingCount.get();
194 }
195
196 public long getEvictionCount() {
197 return evictionCount.get();
198 }
199
200 public long getEvictedCount() {
201 return this.evictedBlockCount.get();
202 }
203
204 public long getPrimaryEvictedCount() {
205 return primaryEvictedBlockCount.get();
206 }
207
208 public double getHitRatio() {
209 return ((float)getHitCount()/(float)getRequestCount());
210 }
211
212 public double getHitCachingRatio() {
213 return ((float)getHitCachingCount()/(float)getRequestCachingCount());
214 }
215
216 public double getMissRatio() {
217 return ((float)getMissCount()/(float)getRequestCount());
218 }
219
220 public double getMissCachingRatio() {
221 return ((float)getMissCachingCount()/(float)getRequestCachingCount());
222 }
223
224 public double evictedPerEviction() {
225 return ((float)getEvictedCount()/(float)getEvictionCount());
226 }
227
228 public long getFailedInserts() {
229 return failedInserts.get();
230 }
231
232 public void rollMetricsPeriod() {
233 hitCounts[windowIndex] = getHitCount() - lastHitCount;
234 lastHitCount = getHitCount();
235 hitCachingCounts[windowIndex] =
236 getHitCachingCount() - lastHitCachingCount;
237 lastHitCachingCount = getHitCachingCount();
238 requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
239 lastRequestCount = getRequestCount();
240 requestCachingCounts[windowIndex] =
241 getRequestCachingCount() - lastRequestCachingCount;
242 lastRequestCachingCount = getRequestCachingCount();
243 windowIndex = (windowIndex + 1) % numPeriodsInWindow;
244 }
245
246 public long getSumHitCountsPastNPeriods() {
247 return sum(hitCounts);
248 }
249
250 public long getSumRequestCountsPastNPeriods() {
251 return sum(requestCounts);
252 }
253
254 public long getSumHitCachingCountsPastNPeriods() {
255 return sum(hitCachingCounts);
256 }
257
258 public long getSumRequestCachingCountsPastNPeriods() {
259 return sum(requestCachingCounts);
260 }
261
262 public double getHitRatioPastNPeriods() {
263 double ratio = ((double)getSumHitCountsPastNPeriods() /
264 (double)getSumRequestCountsPastNPeriods());
265 return Double.isNaN(ratio) ? 0 : ratio;
266 }
267
268 public double getHitCachingRatioPastNPeriods() {
269 double ratio = ((double)getSumHitCachingCountsPastNPeriods() /
270 (double)getSumRequestCachingCountsPastNPeriods());
271 return Double.isNaN(ratio) ? 0 : ratio;
272 }
273
274 public AgeSnapshot getAgeAtEvictionSnapshot() {
275 return new AgeSnapshot(this.ageAtEviction);
276 }
277
278 private static long sum(long [] counts) {
279 long sum = 0;
280 for (long count : counts) sum += count;
281 return sum;
282 }
283
284 private static long [] initializeZeros(int n) {
285 long [] zeros = new long [n];
286 for (int i=0; i<n; i++) {
287 zeros[i] = 0L;
288 }
289 return zeros;
290 }
291 }