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  import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram;
25  
26  import org.apache.hadoop.hbase.util.Counter;
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) {
251       this.ageAtEviction.add((t - this.startTime) / BlockCacheUtil.NANOS_PER_SECOND, 1);
252     }
253     this.evictedBlockCount.increment();
254     if (primary) {
255       primaryEvictedBlockCount.increment();
256     }
257   }
258 
259   public long failInsert() {
260     return failedInserts.incrementAndGet();
261   }
262 
263 
264   // All of the counts of misses and hits.
265   public long getDataMissCount() {
266     return dataMissCount.get();
267   }
268 
269   public long getLeafIndexMissCount() {
270     return leafIndexMissCount.get();
271   }
272 
273   public long getBloomChunkMissCount() {
274     return bloomChunkMissCount.get();
275   }
276 
277   public long getMetaMissCount() {
278     return metaMissCount.get();
279   }
280 
281   public long getRootIndexMissCount() {
282     return rootIndexMissCount.get();
283   }
284 
285   public long getIntermediateIndexMissCount() {
286     return intermediateIndexMissCount.get();
287   }
288 
289   public long getFileInfoMissCount() {
290     return fileInfoMissCount.get();
291   }
292 
293   public long getGeneralBloomMetaMissCount() {
294     return generalBloomMetaMissCount.get();
295   }
296 
297   public long getDeleteFamilyBloomMissCount() {
298     return deleteFamilyBloomMissCount.get();
299   }
300 
301   public long getTrailerMissCount() {
302     return trailerMissCount.get();
303   }
304 
305   public long getDataHitCount() {
306     return dataHitCount.get();
307   }
308 
309   public long getLeafIndexHitCount() {
310     return leafIndexHitCount.get();
311   }
312 
313   public long getBloomChunkHitCount() {
314     return bloomChunkHitCount.get();
315   }
316 
317   public long getMetaHitCount() {
318     return metaHitCount.get();
319   }
320 
321   public long getRootIndexHitCount() {
322     return rootIndexHitCount.get();
323   }
324 
325   public long getIntermediateIndexHitCount() {
326     return intermediateIndexHitCount.get();
327   }
328 
329   public long getFileInfoHitCount() {
330     return fileInfoHitCount.get();
331   }
332 
333   public long getGeneralBloomMetaHitCount() {
334     return generalBloomMetaHitCount.get();
335   }
336 
337   public long getDeleteFamilyBloomHitCount() {
338     return deleteFamilyBloomHitCount.get();
339   }
340 
341   public long getTrailerHitCount() {
342     return trailerHitCount.get();
343   }
344 
345   public long getRequestCount() {
346     return getHitCount() + getMissCount();
347   }
348 
349   public long getRequestCachingCount() {
350     return getHitCachingCount() + getMissCachingCount();
351   }
352 
353   public long getMissCount() {
354     return missCount.get();
355   }
356 
357   public long getPrimaryMissCount() {
358     return primaryMissCount.get();
359   }
360 
361   public long getMissCachingCount() {
362     return missCachingCount.get();
363   }
364 
365   public long getHitCount() {
366     return hitCount.get();
367   }
368 
369   public long getPrimaryHitCount() {
370     return primaryHitCount.get();
371   }
372 
373   public long getHitCachingCount() {
374     return hitCachingCount.get();
375   }
376 
377   public long getEvictionCount() {
378     return evictionCount.get();
379   }
380 
381   public long getEvictedCount() {
382     return this.evictedBlockCount.get();
383   }
384 
385   public long getPrimaryEvictedCount() {
386     return primaryEvictedBlockCount.get();
387   }
388 
389   public double getHitRatio() {
390     double requestCount = getRequestCount();
391 
392     if (requestCount == 0) {
393       return 0;
394     }
395 
396     return getHitCount() / requestCount;
397   }
398 
399   public double getHitCachingRatio() {
400     double requestCachingCount = getRequestCachingCount();
401 
402     if (requestCachingCount == 0) {
403       return 0;
404     }
405 
406     return getHitCachingCount() / requestCachingCount;
407   }
408 
409   public double getMissRatio() {
410     double requestCount = getRequestCount();
411 
412     if (requestCount == 0) {
413       return 0;
414     }
415 
416     return getMissCount() / requestCount;
417   }
418 
419   public double getMissCachingRatio() {
420     double requestCachingCount = getRequestCachingCount();
421 
422     if (requestCachingCount == 0) {
423       return 0;
424     }
425 
426     return getMissCachingCount() / requestCachingCount;
427   }
428 
429   public double evictedPerEviction() {
430     double evictionCount = getEvictionCount();
431 
432     if (evictionCount == 0) {
433       return 0;
434     }
435 
436     return getEvictedCount() / evictionCount;
437   }
438 
439   public long getFailedInserts() {
440     return failedInserts.get();
441   }
442 
443   public void rollMetricsPeriod() {
444     hitCounts[windowIndex] = getHitCount() - lastHitCount;
445     lastHitCount = getHitCount();
446     hitCachingCounts[windowIndex] =
447       getHitCachingCount() - lastHitCachingCount;
448     lastHitCachingCount = getHitCachingCount();
449     requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
450     lastRequestCount = getRequestCount();
451     requestCachingCounts[windowIndex] =
452       getRequestCachingCount() - lastRequestCachingCount;
453     lastRequestCachingCount = getRequestCachingCount();
454     windowIndex = (windowIndex + 1) % numPeriodsInWindow;
455   }
456 
457   public long getSumHitCountsPastNPeriods() {
458     return sum(hitCounts);
459   }
460 
461   public long getSumRequestCountsPastNPeriods() {
462     return sum(requestCounts);
463   }
464 
465   public long getSumHitCachingCountsPastNPeriods() {
466     return sum(hitCachingCounts);
467   }
468 
469   public long getSumRequestCachingCountsPastNPeriods() {
470     return sum(requestCachingCounts);
471   }
472 
473   public double getHitRatioPastNPeriods() {
474     double ratio = ((double)getSumHitCountsPastNPeriods() /
475         (double)getSumRequestCountsPastNPeriods());
476     return Double.isNaN(ratio) ? 0 : ratio;
477   }
478 
479   public double getHitCachingRatioPastNPeriods() {
480     double ratio = ((double)getSumHitCachingCountsPastNPeriods() /
481         (double)getSumRequestCachingCountsPastNPeriods());
482     return Double.isNaN(ratio) ? 0 : ratio;
483   }
484 
485   public AgeSnapshot getAgeAtEvictionSnapshot() {
486     return new AgeSnapshot(this.ageAtEviction);
487   }
488 
489   private static long sum(long [] counts) {
490     long sum = 0;
491     for (long count : counts) sum += count;
492     return sum;
493   }
494 
495   private static long [] initializeZeros(int n) {
496     long [] zeros = new long [n];
497     for (int i=0; i<n; i++) {
498       zeros[i] = 0L;
499     }
500     return zeros;
501   }
502 }