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  /**
26   * Class that implements cache metrics.
27   */
28  @InterfaceAudience.Private
29  public class CacheStats {
30    /** Sliding window statistics. The number of metric periods to include in
31     * sliding window hit ratio calculations.
32     */
33    static final int DEFAULT_WINDOW_PERIODS = 5;
34  
35    /** The number of getBlock requests that were cache hits */
36    private final AtomicLong hitCount = new AtomicLong(0);
37  
38    /**
39     * The number of getBlock requests that were cache hits, but only from
40     * requests that were set to use the block cache.  This is because all reads
41     * attempt to read from the block cache even if they will not put new blocks
42     * into the block cache.  See HBASE-2253 for more information.
43     */
44    private final AtomicLong hitCachingCount = new AtomicLong(0);
45  
46    /** The number of getBlock requests that were cache misses */
47    private final AtomicLong missCount = new AtomicLong(0);
48  
49    /**
50     * The number of getBlock requests that were cache misses, but only from
51     * requests that were set to use the block cache.
52     */
53    private final AtomicLong missCachingCount = new AtomicLong(0);
54  
55    /** The number of times an eviction has occurred */
56    private final AtomicLong evictionCount = new AtomicLong(0);
57  
58    /** The total number of blocks that have been evicted */
59    private final AtomicLong evictedBlockCount = new AtomicLong(0);
60  
61    /** The total number of blocks that were not inserted. */
62    private final AtomicLong failedInserts = new AtomicLong(0);
63  
64    /** Per Block Type Counts */
65    private final AtomicLong dataMissCount = new AtomicLong(0);
66    private final AtomicLong leafIndexMissCount = new AtomicLong(0);
67    private final AtomicLong bloomChunkMissCount = new AtomicLong(0);
68    private final AtomicLong metaMissCount = new AtomicLong(0);
69    private final AtomicLong rootIndexMissCount = new AtomicLong(0);
70    private final AtomicLong intermediateIndexMissCount = new AtomicLong(0);
71    private final AtomicLong fileInfoMissCount = new AtomicLong(0);
72    private final AtomicLong generalBloomMetaMissCount = new AtomicLong(0);
73    private final AtomicLong deleteFamilyBloomMissCount = new AtomicLong(0);
74    private final AtomicLong trailerMissCount = new AtomicLong(0);
75  
76    private final AtomicLong dataHitCount = new AtomicLong(0);
77    private final AtomicLong leafIndexHitCount = new AtomicLong(0);
78    private final AtomicLong bloomChunkHitCount = new AtomicLong(0);
79    private final AtomicLong metaHitCount = new AtomicLong(0);
80    private final AtomicLong rootIndexHitCount = new AtomicLong(0);
81    private final AtomicLong intermediateIndexHitCount = new AtomicLong(0);
82    private final AtomicLong fileInfoHitCount = new AtomicLong(0);
83    private final AtomicLong generalBloomMetaHitCount = new AtomicLong(0);
84    private final AtomicLong deleteFamilyBloomHitCount = new AtomicLong(0);
85    private final AtomicLong trailerHitCount = new AtomicLong(0);
86  
87    /** The number of metrics periods to include in window */
88    private final int numPeriodsInWindow;
89    /** Hit counts for each period in window */
90    private final long [] hitCounts;
91    /** Caching hit counts for each period in window */
92    private final long [] hitCachingCounts;
93    /** Access counts for each period in window */
94    private final long [] requestCounts;
95    /** Caching access counts for each period in window */
96    private final long [] requestCachingCounts;
97    /** Last hit count read */
98    private long lastHitCount = 0;
99    /** Last hit caching count read */
100   private long lastHitCachingCount = 0;
101   /** Last request count read */
102   private long lastRequestCount = 0;
103   /** Last request caching count read */
104   private long lastRequestCachingCount = 0;
105   /** Current window index (next to be updated) */
106   private int windowIndex = 0;
107 
108   public CacheStats() {
109     this(DEFAULT_WINDOW_PERIODS);
110   }
111 
112   public CacheStats(int numPeriodsInWindow) {
113     this.numPeriodsInWindow = numPeriodsInWindow;
114     this.hitCounts = initializeZeros(numPeriodsInWindow);
115     this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
116     this.requestCounts = initializeZeros(numPeriodsInWindow);
117     this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
118   }
119 
120   public void miss(boolean caching) {
121     missCount.incrementAndGet();
122     if (caching) missCachingCount.incrementAndGet();
123   }
124 
125   @Override
126   public String toString() {
127     return "hitCount=" + getHitCount() + ", hitCachingCount=" + getHitCachingCount() +
128       ", missCount=" + getMissCount() + ", missCachingCount=" + getMissCachingCount() +
129       ", evictionCount=" + getEvictionCount() +
130       ", evictedBlockCount=" + getEvictedCount();
131   }
132 
133   public void miss(boolean caching, BlockType type) {
134     missCount.incrementAndGet();
135     if (caching) missCachingCount.incrementAndGet();
136     if (type == null) {
137       return;
138     }
139     switch (type) {
140       case DATA:
141       case ENCODED_DATA:
142         dataMissCount.incrementAndGet();
143         break;
144       case LEAF_INDEX:
145         leafIndexMissCount.incrementAndGet();
146         break;
147       case BLOOM_CHUNK:
148         bloomChunkMissCount.incrementAndGet();
149         break;
150       case META:
151         metaMissCount.incrementAndGet();
152         break;
153       case INTERMEDIATE_INDEX:
154         intermediateIndexMissCount.incrementAndGet();
155         break;
156       case ROOT_INDEX:
157         rootIndexMissCount.incrementAndGet();
158         break;
159       case FILE_INFO:
160         fileInfoMissCount.incrementAndGet();
161         break;
162       case GENERAL_BLOOM_META:
163         generalBloomMetaMissCount.incrementAndGet();
164         break;
165       case DELETE_FAMILY_BLOOM_META:
166         deleteFamilyBloomMissCount.incrementAndGet();
167         break;
168       case TRAILER:
169         trailerMissCount.incrementAndGet();
170         break;
171       default:
172         // If there's a new type that's fine
173         // Ignore it for now. This is metrics don't exception.
174         break;
175     }
176   }
177 
178   public void hit(boolean caching, BlockType type) {
179     hitCount.incrementAndGet();
180     if (caching) hitCachingCount.incrementAndGet();
181 
182     if (type == null) {
183       return;
184     }
185     switch (type) {
186       case DATA:
187       case ENCODED_DATA:
188         dataHitCount.incrementAndGet();
189         break;
190       case LEAF_INDEX:
191         leafIndexHitCount.incrementAndGet();
192         break;
193       case BLOOM_CHUNK:
194         bloomChunkHitCount.incrementAndGet();
195         break;
196       case META:
197         metaHitCount.incrementAndGet();
198         break;
199       case INTERMEDIATE_INDEX:
200         intermediateIndexHitCount.incrementAndGet();
201         break;
202       case ROOT_INDEX:
203         rootIndexHitCount.incrementAndGet();
204         break;
205       case FILE_INFO:
206         fileInfoHitCount.incrementAndGet();
207         break;
208       case GENERAL_BLOOM_META:
209         generalBloomMetaHitCount.incrementAndGet();
210         break;
211       case DELETE_FAMILY_BLOOM_META:
212         deleteFamilyBloomHitCount.incrementAndGet();
213         break;
214       case TRAILER:
215         trailerHitCount.incrementAndGet();
216         break;
217       default:
218         // If there's a new type that's fine
219         // Ignore it for now. This is metrics don't exception.
220         break;
221     }
222   }
223 
224   public void evict() {
225     evictionCount.incrementAndGet();
226   }
227 
228   public void evicted() {
229     evictedBlockCount.incrementAndGet();
230   }
231 
232   public long failInsert() {
233     return failedInserts.incrementAndGet();
234   }
235 
236 
237   // All of the counts of misses and hits.
238   public long getDataMissCount() {
239     return dataMissCount.get();
240   }
241 
242   public long getLeafIndexMissCount() {
243     return leafIndexMissCount.get();
244   }
245 
246   public long getBloomChunkMissCount() {
247     return bloomChunkMissCount.get();
248   }
249 
250   public long getMetaMissCount() {
251     return metaMissCount.get();
252   }
253 
254   public long getRootIndexMissCount() {
255     return rootIndexMissCount.get();
256   }
257 
258   public long getIntermediateIndexMissCount() {
259     return intermediateIndexMissCount.get();
260   }
261 
262   public long getFileInfoMissCount() {
263     return fileInfoMissCount.get();
264   }
265 
266   public long getGeneralBloomMetaMissCount() {
267     return generalBloomMetaMissCount.get();
268   }
269 
270   public long getDeleteFamilyBloomMissCount() {
271     return deleteFamilyBloomMissCount.get();
272   }
273 
274   public long getTrailerMissCount() {
275     return trailerMissCount.get();
276   }
277 
278   public long getDataHitCount() {
279     return dataHitCount.get();
280   }
281 
282   public long getLeafIndexHitCount() {
283     return leafIndexHitCount.get();
284   }
285 
286   public long getBloomChunkHitCount() {
287     return bloomChunkHitCount.get();
288   }
289 
290   public long getMetaHitCount() {
291     return metaHitCount.get();
292   }
293 
294   public long getRootIndexHitCount() {
295     return rootIndexHitCount.get();
296   }
297 
298   public long getIntermediateIndexHitCount() {
299     return intermediateIndexHitCount.get();
300   }
301 
302   public long getFileInfoHitCount() {
303     return fileInfoHitCount.get();
304   }
305 
306   public long getGeneralBloomMetaHitCount() {
307     return generalBloomMetaHitCount.get();
308   }
309 
310   public long getDeleteFamilyBloomHitCount() {
311     return deleteFamilyBloomHitCount.get();
312   }
313 
314   public long getTrailerHitCount() {
315     return trailerHitCount.get();
316   }
317 
318   public long getRequestCount() {
319     return getHitCount() + getMissCount();
320   }
321 
322   public long getRequestCachingCount() {
323     return getHitCachingCount() + getMissCachingCount();
324   }
325 
326   public long getMissCount() {
327     return missCount.get();
328   }
329 
330   public long getMissCachingCount() {
331     return missCachingCount.get();
332   }
333 
334   public long getHitCount() {
335     return hitCount.get();
336   }
337 
338   public long getHitCachingCount() {
339     return hitCachingCount.get();
340   }
341 
342   public long getEvictionCount() {
343     return evictionCount.get();
344   }
345 
346   public long getEvictedCount() {
347     return evictedBlockCount.get();
348   }
349 
350   public double getHitRatio() {
351     return ((float)getHitCount()/(float)getRequestCount());
352   }
353 
354   public double getHitCachingRatio() {
355     return ((float)getHitCachingCount()/(float)getRequestCachingCount());
356   }
357 
358   public double getMissRatio() {
359     return ((float)getMissCount()/(float)getRequestCount());
360   }
361 
362   public double getMissCachingRatio() {
363     return ((float)getMissCachingCount()/(float)getRequestCachingCount());
364   }
365 
366   public double evictedPerEviction() {
367     return ((float)getEvictedCount()/(float)getEvictionCount());
368   }
369 
370   public long getFailedInserts() {
371     return failedInserts.get();
372   }
373 
374   public void rollMetricsPeriod() {
375     hitCounts[windowIndex] = getHitCount() - lastHitCount;
376     lastHitCount = getHitCount();
377     hitCachingCounts[windowIndex] =
378       getHitCachingCount() - lastHitCachingCount;
379     lastHitCachingCount = getHitCachingCount();
380     requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
381     lastRequestCount = getRequestCount();
382     requestCachingCounts[windowIndex] =
383       getRequestCachingCount() - lastRequestCachingCount;
384     lastRequestCachingCount = getRequestCachingCount();
385     windowIndex = (windowIndex + 1) % numPeriodsInWindow;
386   }
387 
388   public long getSumHitCountsPastNPeriods() {
389     return sum(hitCounts);
390   }
391 
392   public long getSumRequestCountsPastNPeriods() {
393     return sum(requestCounts);
394   }
395 
396   public long getSumHitCachingCountsPastNPeriods() {
397     return sum(hitCachingCounts);
398   }
399 
400   public long getSumRequestCachingCountsPastNPeriods() {
401     return sum(requestCachingCounts);
402   }
403 
404   public double getHitRatioPastNPeriods() {
405     double ratio = ((double)sum(hitCounts)/(double)sum(requestCounts));
406     return Double.isNaN(ratio) ? 0 : ratio;
407   }
408 
409   public double getHitCachingRatioPastNPeriods() {
410     double ratio =
411       ((double)sum(hitCachingCounts)/(double)sum(requestCachingCounts));
412     return Double.isNaN(ratio) ? 0 : ratio;
413   }
414 
415   private static long sum(long [] counts) {
416     long sum = 0;
417     for (long count : counts) sum += count;
418     return sum;
419   }
420 
421   private static long [] initializeZeros(int n) {
422     long [] zeros = new long [n];
423     for (int i=0; i<n; i++) {
424       zeros[i] = 0L;
425     }
426     return zeros;
427   }
428 }