View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
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 org.apache.hadoop.hbase.util.Counter;
26  import org.apache.hadoop.hbase.util.FastLongHistogram;
27  
28  /**
29   * Class that implements cache metrics.
30   */
31  @InterfaceAudience.Private
32  public class CacheStats {
33  
34    /** Sliding window statistics. The number of metric periods to include in
35     * sliding window hit ratio calculations.
36     */
37    static final int DEFAULT_WINDOW_PERIODS = 5;
38  
39    /** The number of getBlock requests that were cache hits */
40    private final Counter hitCount = new Counter();
41  
42    /** The number of getBlock requests that were cache hits from primary replica */
43    private final Counter primaryHitCount = new Counter();
44  
45    /**
46     * The number of getBlock requests that were cache hits, but only from
47     * requests that were set to use the block cache.  This is because all reads
48     * attempt to read from the block cache even if they will not put new blocks
49     * into the block cache.  See HBASE-2253 for more information.
50     */
51    private final Counter hitCachingCount = new Counter();
52  
53    /** The number of getBlock requests that were cache misses */
54    private final Counter missCount = new Counter();
55  
56    /** The number of getBlock requests for primary replica that were cache misses */
57    private final Counter primaryMissCount = new Counter();
58    /**
59     * The number of getBlock requests that were cache misses, but only from
60     * requests that were set to use the block cache.
61     */
62    private final Counter missCachingCount = new Counter();
63  
64    /** The number of times an eviction has occurred */
65    private final Counter evictionCount = new Counter();
66  
67    /** The total number of blocks that have been evicted */
68    private final Counter evictedBlockCount = new Counter();
69  
70    /** The total number of blocks for primary replica that have been evicted */
71    private final Counter primaryEvictedBlockCount = new Counter();
72  
73    /** The total number of blocks that were not inserted. */
74    private final AtomicLong failedInserts = new AtomicLong(0);
75  
76    /** Per Block Type Counts */
77    private final Counter dataMissCount = new Counter(0);
78    private final Counter leafIndexMissCount = new Counter(0);
79    private final Counter bloomChunkMissCount = new Counter(0);
80    private final Counter metaMissCount = new Counter(0);
81    private final Counter rootIndexMissCount = new Counter(0);
82    private final Counter intermediateIndexMissCount = new Counter(0);
83    private final Counter fileInfoMissCount = new Counter(0);
84    private final Counter generalBloomMetaMissCount = new Counter(0);
85    private final Counter deleteFamilyBloomMissCount = new Counter(0);
86    private final Counter trailerMissCount = new Counter(0);
87  
88    private final Counter dataHitCount = new Counter(0);
89    private final Counter leafIndexHitCount = new Counter(0);
90    private final Counter bloomChunkHitCount = new Counter(0);
91    private final Counter metaHitCount = new Counter(0);
92    private final Counter rootIndexHitCount = new Counter(0);
93    private final Counter intermediateIndexHitCount = new Counter(0);
94    private final Counter fileInfoHitCount = new Counter(0);
95    private final Counter generalBloomMetaHitCount = new Counter(0);
96    private final Counter deleteFamilyBloomHitCount = new Counter(0);
97    private final Counter trailerHitCount = new Counter(0);
98  
99    /** The number of metrics periods to include in window */
100   private final int numPeriodsInWindow;
101   /** Hit counts for each period in window */
102   private final long [] hitCounts;
103   /** Caching hit counts for each period in window */
104   private final long [] hitCachingCounts;
105   /** Access counts for each period in window */
106   private final long [] requestCounts;
107   /** Caching access counts for each period in window */
108   private final long [] requestCachingCounts;
109   /** Last hit count read */
110   private long lastHitCount = 0;
111   /** Last hit caching count read */
112   private long lastHitCachingCount = 0;
113   /** Last request count read */
114   private long lastRequestCount = 0;
115   /** Last request caching count read */
116   private long lastRequestCachingCount = 0;
117   /** Current window index (next to be updated) */
118   private int windowIndex = 0;
119   /**
120    * Keep running age at eviction time
121    */
122   private FastLongHistogram ageAtEviction;
123   private long startTime = System.nanoTime();
124 
125   public CacheStats(final String name) {
126     this(name, DEFAULT_WINDOW_PERIODS);
127   }
128 
129   public CacheStats(final String name, int numPeriodsInWindow) {
130     this.numPeriodsInWindow = numPeriodsInWindow;
131     this.hitCounts = initializeZeros(numPeriodsInWindow);
132     this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
133     this.requestCounts = initializeZeros(numPeriodsInWindow);
134     this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
135     this.ageAtEviction = new FastLongHistogram();
136   }
137 
138   @Override
139   public String toString() {
140     AgeSnapshot snapshot = getAgeAtEvictionSnapshot();
141     return "hitCount=" + getHitCount() + ", hitCachingCount=" + getHitCachingCount() +
142       ", missCount=" + getMissCount() + ", missCachingCount=" + getMissCachingCount() +
143       ", evictionCount=" + getEvictionCount() +
144       ", evictedBlockCount=" + getEvictedCount() +
145       ", primaryMissCount=" + getPrimaryMissCount() +
146       ", primaryHitCount=" + getPrimaryHitCount() +
147       ", evictedAgeMean=" + snapshot.getMean();
148   }
149 
150 
151   public void miss(boolean caching, boolean primary, BlockType type) {
152     missCount.increment();
153     if (primary) primaryMissCount.increment();
154     if (caching) missCachingCount.increment();
155     if (type == null) {
156       return;
157     }
158     switch (type) {
159       case DATA:
160       case ENCODED_DATA:
161         dataMissCount.increment();
162         break;
163       case LEAF_INDEX:
164         leafIndexMissCount.increment();
165         break;
166       case BLOOM_CHUNK:
167         bloomChunkMissCount.increment();
168         break;
169       case META:
170         metaMissCount.increment();
171         break;
172       case INTERMEDIATE_INDEX:
173         intermediateIndexMissCount.increment();
174         break;
175       case ROOT_INDEX:
176         rootIndexMissCount.increment();
177         break;
178       case FILE_INFO:
179         fileInfoMissCount.increment();
180         break;
181       case GENERAL_BLOOM_META:
182         generalBloomMetaMissCount.increment();
183         break;
184       case DELETE_FAMILY_BLOOM_META:
185         deleteFamilyBloomMissCount.increment();
186         break;
187       case TRAILER:
188         trailerMissCount.increment();
189         break;
190       default:
191         // If there's a new type that's fine
192         // Ignore it for now. This is metrics don't exception.
193         break;
194     }
195   }
196 
197   public void hit(boolean caching, boolean primary, BlockType type) {
198     hitCount.increment();
199     if (primary) primaryHitCount.increment();
200     if (caching) hitCachingCount.increment();
201 
202 
203     if (type == null) {
204       return;
205     }
206     switch (type) {
207       case DATA:
208       case ENCODED_DATA:
209         dataHitCount.increment();
210         break;
211       case LEAF_INDEX:
212         leafIndexHitCount.increment();
213         break;
214       case BLOOM_CHUNK:
215         bloomChunkHitCount.increment();
216         break;
217       case META:
218         metaHitCount.increment();
219         break;
220       case INTERMEDIATE_INDEX:
221         intermediateIndexHitCount.increment();
222         break;
223       case ROOT_INDEX:
224         rootIndexHitCount.increment();
225         break;
226       case FILE_INFO:
227         fileInfoHitCount.increment();
228         break;
229       case GENERAL_BLOOM_META:
230         generalBloomMetaHitCount.increment();
231         break;
232       case DELETE_FAMILY_BLOOM_META:
233         deleteFamilyBloomHitCount.increment();
234         break;
235       case TRAILER:
236         trailerHitCount.increment();
237         break;
238       default:
239         // If there's a new type that's fine
240         // Ignore it for now. This is metrics don't exception.
241         break;
242     }
243   }
244 
245   public void evict() {
246     evictionCount.increment();
247   }
248 
249   public void evicted(final long t, boolean primary) {
250     if (t > this.startTime) this.ageAtEviction.add(t - this.startTime,1);
251     this.evictedBlockCount.increment();
252     if (primary) {
253       primaryEvictedBlockCount.increment();
254     }
255   }
256 
257   public long failInsert() {
258     return failedInserts.incrementAndGet();
259   }
260 
261 
262   // All of the counts of misses and hits.
263   public long getDataMissCount() {
264     return dataMissCount.get();
265   }
266 
267   public long getLeafIndexMissCount() {
268     return leafIndexMissCount.get();
269   }
270 
271   public long getBloomChunkMissCount() {
272     return bloomChunkMissCount.get();
273   }
274 
275   public long getMetaMissCount() {
276     return metaMissCount.get();
277   }
278 
279   public long getRootIndexMissCount() {
280     return rootIndexMissCount.get();
281   }
282 
283   public long getIntermediateIndexMissCount() {
284     return intermediateIndexMissCount.get();
285   }
286 
287   public long getFileInfoMissCount() {
288     return fileInfoMissCount.get();
289   }
290 
291   public long getGeneralBloomMetaMissCount() {
292     return generalBloomMetaMissCount.get();
293   }
294 
295   public long getDeleteFamilyBloomMissCount() {
296     return deleteFamilyBloomMissCount.get();
297   }
298 
299   public long getTrailerMissCount() {
300     return trailerMissCount.get();
301   }
302 
303   public long getDataHitCount() {
304     return dataHitCount.get();
305   }
306 
307   public long getLeafIndexHitCount() {
308     return leafIndexHitCount.get();
309   }
310 
311   public long getBloomChunkHitCount() {
312     return bloomChunkHitCount.get();
313   }
314 
315   public long getMetaHitCount() {
316     return metaHitCount.get();
317   }
318 
319   public long getRootIndexHitCount() {
320     return rootIndexHitCount.get();
321   }
322 
323   public long getIntermediateIndexHitCount() {
324     return intermediateIndexHitCount.get();
325   }
326 
327   public long getFileInfoHitCount() {
328     return fileInfoHitCount.get();
329   }
330 
331   public long getGeneralBloomMetaHitCount() {
332     return generalBloomMetaHitCount.get();
333   }
334 
335   public long getDeleteFamilyBloomHitCount() {
336     return deleteFamilyBloomHitCount.get();
337   }
338 
339   public long getTrailerHitCount() {
340     return trailerHitCount.get();
341   }
342 
343   public long getRequestCount() {
344     return getHitCount() + getMissCount();
345   }
346 
347   public long getRequestCachingCount() {
348     return getHitCachingCount() + getMissCachingCount();
349   }
350 
351   public long getMissCount() {
352     return missCount.get();
353   }
354 
355   public long getPrimaryMissCount() {
356     return primaryMissCount.get();
357   }
358 
359   public long getMissCachingCount() {
360     return missCachingCount.get();
361   }
362 
363   public long getHitCount() {
364     return hitCount.get();
365   }
366 
367   public long getPrimaryHitCount() {
368     return primaryHitCount.get();
369   }
370 
371   public long getHitCachingCount() {
372     return hitCachingCount.get();
373   }
374 
375   public long getEvictionCount() {
376     return evictionCount.get();
377   }
378 
379   public long getEvictedCount() {
380     return this.evictedBlockCount.get();
381   }
382 
383   public long getPrimaryEvictedCount() {
384     return primaryEvictedBlockCount.get();
385   }
386 
387   public double getHitRatio() {
388     double requestCount = getRequestCount();
389 
390     if (requestCount == 0) {
391       return 0;
392     }
393 
394     return getHitCount() / requestCount;
395   }
396 
397   public double getHitCachingRatio() {
398     double requestCachingCount = getRequestCachingCount();
399 
400     if (requestCachingCount == 0) {
401       return 0;
402     }
403 
404     return getHitCachingCount() / requestCachingCount;
405   }
406 
407   public double getMissRatio() {
408     double requestCount = getRequestCount();
409 
410     if (requestCount == 0) {
411       return 0;
412     }
413 
414     return getMissCount() / requestCount;
415   }
416 
417   public double getMissCachingRatio() {
418     double requestCachingCount = getRequestCachingCount();
419 
420     if (requestCachingCount == 0) {
421       return 0;
422     }
423 
424     return getMissCachingCount() / requestCachingCount;
425   }
426 
427   public double evictedPerEviction() {
428     double evictionCount = getEvictionCount();
429 
430     if (evictionCount == 0) {
431       return 0;
432     }
433 
434     return getEvictedCount() / evictionCount;
435   }
436 
437   public long getFailedInserts() {
438     return failedInserts.get();
439   }
440 
441   public void rollMetricsPeriod() {
442     hitCounts[windowIndex] = getHitCount() - lastHitCount;
443     lastHitCount = getHitCount();
444     hitCachingCounts[windowIndex] =
445       getHitCachingCount() - lastHitCachingCount;
446     lastHitCachingCount = getHitCachingCount();
447     requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
448     lastRequestCount = getRequestCount();
449     requestCachingCounts[windowIndex] =
450       getRequestCachingCount() - lastRequestCachingCount;
451     lastRequestCachingCount = getRequestCachingCount();
452     windowIndex = (windowIndex + 1) % numPeriodsInWindow;
453   }
454 
455   public long getSumHitCountsPastNPeriods() {
456     return sum(hitCounts);
457   }
458 
459   public long getSumRequestCountsPastNPeriods() {
460     return sum(requestCounts);
461   }
462 
463   public long getSumHitCachingCountsPastNPeriods() {
464     return sum(hitCachingCounts);
465   }
466 
467   public long getSumRequestCachingCountsPastNPeriods() {
468     return sum(requestCachingCounts);
469   }
470 
471   public double getHitRatioPastNPeriods() {
472     double ratio = ((double)getSumHitCountsPastNPeriods() /
473         (double)getSumRequestCountsPastNPeriods());
474     return Double.isNaN(ratio) ? 0 : ratio;
475   }
476 
477   public double getHitCachingRatioPastNPeriods() {
478     double ratio = ((double)getSumHitCachingCountsPastNPeriods() /
479         (double)getSumRequestCachingCountsPastNPeriods());
480     return Double.isNaN(ratio) ? 0 : ratio;
481   }
482 
483   public AgeSnapshot getAgeAtEvictionSnapshot() {
484     return new AgeSnapshot(this.ageAtEviction);
485   }
486 
487   private static long sum(long [] counts) {
488     long sum = 0;
489     for (long count : counts) sum += count;
490     return sum;
491   }
492 
493   private static long [] initializeZeros(int n) {
494     long [] zeros = new long [n];
495     for (int i=0; i<n; i++) {
496       zeros[i] = 0L;
497     }
498     return zeros;
499   }
500 }