View Javadoc

1   /**
2    * Copyright 2011 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.io.hfile;
21  
22  import java.util.concurrent.atomic.AtomicLong;
23  
24  /**
25   * Class that implements cache metrics.
26   */
27  public class CacheStats {
28  
29    /** Sliding window statistics. The number of metric periods to include in
30     * sliding window hit ratio calculations.
31     */
32    static final int DEFAULT_WINDOW_PERIODS = 5;
33  
34    /** The number of getBlock requests that were cache hits */
35    private final AtomicLong hitCount = new AtomicLong(0);
36    /**
37     * The number of getBlock requests that were cache hits, but only from
38     * requests that were set to use the block cache.  This is because all reads
39     * attempt to read from the block cache even if they will not put new blocks
40     * into the block cache.  See HBASE-2253 for more information.
41     */
42    private final AtomicLong hitCachingCount = new AtomicLong(0);
43    /** The number of getBlock requests that were cache misses */
44    private final AtomicLong missCount = new AtomicLong(0);
45    /**
46     * The number of getBlock requests that were cache misses, but only from
47     * requests that were set to use the block cache.
48     */
49    private final AtomicLong missCachingCount = new AtomicLong(0);
50    /** The number of times an eviction has occurred */
51    private final AtomicLong evictionCount = new AtomicLong(0);
52    /** The total number of blocks that have been evicted */
53    private final AtomicLong evictedBlockCount = new AtomicLong(0);
54  
55    /** The number of metrics periods to include in window */
56    private final int numPeriodsInWindow;
57    /** Hit counts for each period in window */
58    private final long [] hitCounts;
59    /** Caching hit counts for each period in window */
60    private final long [] hitCachingCounts;
61    /** Access counts for each period in window */
62    private final long [] requestCounts;
63    /** Caching access counts for each period in window */
64    private final long [] requestCachingCounts;
65    /** Last hit count read */
66    private long lastHitCount = 0;
67    /** Last hit caching count read */
68    private long lastHitCachingCount = 0;
69    /** Last request count read */
70    private long lastRequestCount = 0;
71    /** Last request caching count read */
72    private long lastRequestCachingCount = 0;
73    /** Current window index (next to be updated) */
74    private int windowIndex = 0;
75  
76    public CacheStats() {
77      this(DEFAULT_WINDOW_PERIODS);
78    }
79  
80    public CacheStats(int numPeriodsInWindow) {
81      this.numPeriodsInWindow = numPeriodsInWindow;
82      this.hitCounts = initializeZeros(numPeriodsInWindow);
83      this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
84      this.requestCounts = initializeZeros(numPeriodsInWindow);
85      this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
86    }
87  
88    public void miss(boolean caching) {
89      missCount.incrementAndGet();
90      if (caching) missCachingCount.incrementAndGet();
91    }
92  
93    public void hit(boolean caching) {
94      hitCount.incrementAndGet();
95      if (caching) hitCachingCount.incrementAndGet();
96    }
97  
98    public void evict() {
99      evictionCount.incrementAndGet();
100   }
101 
102   public void evicted() {
103     evictedBlockCount.incrementAndGet();
104   }
105 
106   public long getRequestCount() {
107     return getHitCount() + getMissCount();
108   }
109 
110   public long getRequestCachingCount() {
111     return getHitCachingCount() + getMissCachingCount();
112   }
113 
114   public long getMissCount() {
115     return missCount.get();
116   }
117 
118   public long getMissCachingCount() {
119     return missCachingCount.get();
120   }
121 
122   public long getHitCount() {
123     return hitCount.get();
124   }
125 
126   public long getHitCachingCount() {
127     return hitCachingCount.get();
128   }
129 
130   public long getEvictionCount() {
131     return evictionCount.get();
132   }
133 
134   public long getEvictedCount() {
135     return evictedBlockCount.get();
136   }
137 
138   public double getHitRatio() {
139     return ((float)getHitCount()/(float)getRequestCount());
140   }
141 
142   public double getHitCachingRatio() {
143     return ((float)getHitCachingCount()/(float)getRequestCachingCount());
144   }
145 
146   public double getMissRatio() {
147     return ((float)getMissCount()/(float)getRequestCount());
148   }
149 
150   public double getMissCachingRatio() {
151     return ((float)getMissCachingCount()/(float)getRequestCachingCount());
152   }
153 
154   public double evictedPerEviction() {
155     return ((float)getEvictedCount()/(float)getEvictionCount());
156   }
157 
158   public void rollMetricsPeriod() {
159     hitCounts[windowIndex] = getHitCount() - lastHitCount;
160     lastHitCount = getHitCount();
161     hitCachingCounts[windowIndex] =
162       getHitCachingCount() - lastHitCachingCount;
163     lastHitCachingCount = getHitCachingCount();
164     requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
165     lastRequestCount = getRequestCount();
166     requestCachingCounts[windowIndex] =
167       getRequestCachingCount() - lastRequestCachingCount;
168     lastRequestCachingCount = getRequestCachingCount();
169     windowIndex = (windowIndex + 1) % numPeriodsInWindow;
170   }
171 
172   public double getHitRatioPastNPeriods() {
173     double ratio = ((double)sum(hitCounts)/(double)sum(requestCounts));
174     return Double.isNaN(ratio) ? 0 : ratio;
175   }
176 
177   public double getHitCachingRatioPastNPeriods() {
178     double ratio =
179       ((double)sum(hitCachingCounts)/(double)sum(requestCachingCounts));
180     return Double.isNaN(ratio) ? 0 : ratio;
181   }
182 
183   private static long sum(long [] counts) {
184     long sum = 0;
185     for (long count : counts) sum += count;
186     return sum;
187   }
188 
189   private static long [] initializeZeros(int n) {
190     long [] zeros = new long [n];
191     for (int i=0; i<n; i++) {
192       zeros[i] = 0L;
193     }
194     return zeros;
195   }
196 }