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
48
49
50
51
52 private final AtomicLong hitCachingCount = new AtomicLong(0);
53
54
55 private final AtomicLong missCount = new AtomicLong(0);
56
57
58
59
60
61 private final AtomicLong missCachingCount = new AtomicLong(0);
62
63
64 private final AtomicLong evictionCount = new AtomicLong(0);
65
66
67 private final AtomicLong evictedBlockCount = new AtomicLong(0);
68
69
70 private final int numPeriodsInWindow;
71
72 private final long [] hitCounts;
73
74 private final long [] hitCachingCounts;
75
76 private final long [] requestCounts;
77
78 private final long [] requestCachingCounts;
79
80 private long lastHitCount = 0;
81
82 private long lastHitCachingCount = 0;
83
84 private long lastRequestCount = 0;
85
86 private long lastRequestCachingCount = 0;
87
88 private int windowIndex = 0;
89
90
91
92 private Histogram ageAtEviction;
93 private long startTime = System.nanoTime();
94
95 public CacheStats(final String name) {
96 this(name, DEFAULT_WINDOW_PERIODS);
97 }
98
99 public CacheStats(final String name, int numPeriodsInWindow) {
100 this.numPeriodsInWindow = numPeriodsInWindow;
101 this.hitCounts = initializeZeros(numPeriodsInWindow);
102 this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
103 this.requestCounts = initializeZeros(numPeriodsInWindow);
104 this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
105 this.ageAtEviction = METRICS.newHistogram(CacheStats.class, name + ".ageAtEviction");
106 }
107
108 @Override
109 public String toString() {
110 AgeSnapshot snapshot = getAgeAtEvictionSnapshot();
111 return "hitCount=" + getHitCount() + ", hitCachingCount=" + getHitCachingCount() +
112 ", missCount=" + getMissCount() + ", missCachingCount=" + getMissCachingCount() +
113 ", evictionCount=" + getEvictionCount() +
114 ", evictedBlockCount=" + getEvictedCount() +
115 ", evictedAgeMean=" + snapshot.getMean() +
116 ", evictedAgeStdDev=" + snapshot.getStdDev();
117 }
118
119 public void miss(boolean caching) {
120 missCount.incrementAndGet();
121 if (caching) missCachingCount.incrementAndGet();
122 }
123
124 public void hit(boolean caching) {
125 hitCount.incrementAndGet();
126 if (caching) hitCachingCount.incrementAndGet();
127 }
128
129 public void evict() {
130 evictionCount.incrementAndGet();
131 }
132
133 public void evicted(final long t) {
134 if (t > this.startTime) this.ageAtEviction.update(t - this.startTime);
135 this.evictedBlockCount.incrementAndGet();
136 }
137
138 public long getRequestCount() {
139 return getHitCount() + getMissCount();
140 }
141
142 public long getRequestCachingCount() {
143 return getHitCachingCount() + getMissCachingCount();
144 }
145
146 public long getMissCount() {
147 return missCount.get();
148 }
149
150 public long getMissCachingCount() {
151 return missCachingCount.get();
152 }
153
154 public long getHitCount() {
155 return hitCount.get();
156 }
157
158 public long getHitCachingCount() {
159 return hitCachingCount.get();
160 }
161
162 public long getEvictionCount() {
163 return evictionCount.get();
164 }
165
166 public long getEvictedCount() {
167 return this.evictedBlockCount.get();
168 }
169
170 public double getHitRatio() {
171 return ((float)getHitCount()/(float)getRequestCount());
172 }
173
174 public double getHitCachingRatio() {
175 return ((float)getHitCachingCount()/(float)getRequestCachingCount());
176 }
177
178 public double getMissRatio() {
179 return ((float)getMissCount()/(float)getRequestCount());
180 }
181
182 public double getMissCachingRatio() {
183 return ((float)getMissCachingCount()/(float)getRequestCachingCount());
184 }
185
186 public double evictedPerEviction() {
187 return ((float)getEvictedCount()/(float)getEvictionCount());
188 }
189
190 public void rollMetricsPeriod() {
191 hitCounts[windowIndex] = getHitCount() - lastHitCount;
192 lastHitCount = getHitCount();
193 hitCachingCounts[windowIndex] =
194 getHitCachingCount() - lastHitCachingCount;
195 lastHitCachingCount = getHitCachingCount();
196 requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
197 lastRequestCount = getRequestCount();
198 requestCachingCounts[windowIndex] =
199 getRequestCachingCount() - lastRequestCachingCount;
200 lastRequestCachingCount = getRequestCachingCount();
201 windowIndex = (windowIndex + 1) % numPeriodsInWindow;
202 }
203
204 public long getSumHitCountsPastNPeriods() {
205 return sum(hitCounts);
206 }
207
208 public long getSumRequestCountsPastNPeriods() {
209 return sum(requestCounts);
210 }
211
212 public long getSumHitCachingCountsPastNPeriods() {
213 return sum(hitCachingCounts);
214 }
215
216 public long getSumRequestCachingCountsPastNPeriods() {
217 return sum(requestCachingCounts);
218 }
219
220 public double getHitRatioPastNPeriods() {
221 double ratio = ((double)sum(hitCounts)/(double)sum(requestCounts));
222 return Double.isNaN(ratio) ? 0 : ratio;
223 }
224
225 public double getHitCachingRatioPastNPeriods() {
226 double ratio =
227 ((double)sum(hitCachingCounts)/(double)sum(requestCachingCounts));
228 return Double.isNaN(ratio) ? 0 : ratio;
229 }
230
231 public AgeSnapshot getAgeAtEvictionSnapshot() {
232 return new AgeSnapshot(this.ageAtEviction);
233 }
234
235 private static long sum(long [] counts) {
236 long sum = 0;
237 for (long count : counts) sum += count;
238 return sum;
239 }
240
241 private static long [] initializeZeros(int n) {
242 long [] zeros = new long [n];
243 for (int i=0; i<n; i++) {
244 zeros[i] = 0L;
245 }
246 return zeros;
247 }
248 }