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.classification.InterfaceAudience;
24  
25  /**
26   * Class that implements cache metrics.
27   */
28  @InterfaceAudience.Private
29  public class CacheStats {
30  
31    /** Sliding window statistics. The number of metric periods to include in
32     * sliding window hit ratio calculations.
33     */
34    static final int DEFAULT_WINDOW_PERIODS = 5;
35  
36    /** The number of getBlock requests that were cache hits */
37    private final AtomicLong hitCount = new AtomicLong(0);
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    /** The number of getBlock requests that were cache misses */
46    private final AtomicLong missCount = new AtomicLong(0);
47    /**
48     * The number of getBlock requests that were cache misses, but only from
49     * requests that were set to use the block cache.
50     */
51    private final AtomicLong missCachingCount = new AtomicLong(0);
52    /** The number of times an eviction has occurred */
53    private final AtomicLong evictionCount = new AtomicLong(0);
54    /** The total number of blocks that have been evicted */
55    private final AtomicLong evictedBlockCount = new AtomicLong(0);
56  
57    /** The number of metrics periods to include in window */
58    private final int numPeriodsInWindow;
59    /** Hit counts for each period in window */
60    private final long [] hitCounts;
61    /** Caching hit counts for each period in window */
62    private final long [] hitCachingCounts;
63    /** Access counts for each period in window */
64    private final long [] requestCounts;
65    /** Caching access counts for each period in window */
66    private final long [] requestCachingCounts;
67    /** Last hit count read */
68    private long lastHitCount = 0;
69    /** Last hit caching count read */
70    private long lastHitCachingCount = 0;
71    /** Last request count read */
72    private long lastRequestCount = 0;
73    /** Last request caching count read */
74    private long lastRequestCachingCount = 0;
75    /** Current window index (next to be updated) */
76    private int windowIndex = 0;
77  
78    public CacheStats() {
79      this(DEFAULT_WINDOW_PERIODS);
80    }
81  
82    public CacheStats(int numPeriodsInWindow) {
83      this.numPeriodsInWindow = numPeriodsInWindow;
84      this.hitCounts = initializeZeros(numPeriodsInWindow);
85      this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
86      this.requestCounts = initializeZeros(numPeriodsInWindow);
87      this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
88    }
89  
90    public void miss(boolean caching) {
91      missCount.incrementAndGet();
92      if (caching) missCachingCount.incrementAndGet();
93    }
94  
95    public void hit(boolean caching) {
96      hitCount.incrementAndGet();
97      if (caching) hitCachingCount.incrementAndGet();
98    }
99  
100   public void evict() {
101     evictionCount.incrementAndGet();
102   }
103 
104   public void evicted() {
105     evictedBlockCount.incrementAndGet();
106   }
107 
108   public long getRequestCount() {
109     return getHitCount() + getMissCount();
110   }
111 
112   public long getRequestCachingCount() {
113     return getHitCachingCount() + getMissCachingCount();
114   }
115 
116   public long getMissCount() {
117     return missCount.get();
118   }
119 
120   public long getMissCachingCount() {
121     return missCachingCount.get();
122   }
123 
124   public long getHitCount() {
125     return hitCount.get();
126   }
127 
128   public long getHitCachingCount() {
129     return hitCachingCount.get();
130   }
131 
132   public long getEvictionCount() {
133     return evictionCount.get();
134   }
135 
136   public long getEvictedCount() {
137     return evictedBlockCount.get();
138   }
139 
140   public double getHitRatio() {
141     return ((float)getHitCount()/(float)getRequestCount());
142   }
143 
144   public double getHitCachingRatio() {
145     return ((float)getHitCachingCount()/(float)getRequestCachingCount());
146   }
147 
148   public double getMissRatio() {
149     return ((float)getMissCount()/(float)getRequestCount());
150   }
151 
152   public double getMissCachingRatio() {
153     return ((float)getMissCachingCount()/(float)getRequestCachingCount());
154   }
155 
156   public double evictedPerEviction() {
157     return ((float)getEvictedCount()/(float)getEvictionCount());
158   }
159 
160   public void rollMetricsPeriod() {
161     hitCounts[windowIndex] = getHitCount() - lastHitCount;
162     lastHitCount = getHitCount();
163     hitCachingCounts[windowIndex] =
164       getHitCachingCount() - lastHitCachingCount;
165     lastHitCachingCount = getHitCachingCount();
166     requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
167     lastRequestCount = getRequestCount();
168     requestCachingCounts[windowIndex] =
169       getRequestCachingCount() - lastRequestCachingCount;
170     lastRequestCachingCount = getRequestCachingCount();
171     windowIndex = (windowIndex + 1) % numPeriodsInWindow;
172   }
173 
174   public long getSumHitCountsPastNPeriods() {
175     return sum(hitCounts);
176   }
177 
178   public long getSumRequestCountsPastNPeriods() {
179     return sum(requestCounts);
180   }
181 
182   public long getSumHitCachingCountsPastNPeriods() {
183     return sum(hitCachingCounts);
184   }
185 
186   public long getSumRequestCachingCountsPastNPeriods() {
187     return sum(requestCachingCounts);
188   }
189 
190   public double getHitRatioPastNPeriods() {
191     double ratio = ((double)sum(hitCounts)/(double)sum(requestCounts));
192     return Double.isNaN(ratio) ? 0 : ratio;
193   }
194 
195   public double getHitCachingRatioPastNPeriods() {
196     double ratio =
197       ((double)sum(hitCachingCounts)/(double)sum(requestCachingCounts));
198     return Double.isNaN(ratio) ? 0 : ratio;
199   }
200 
201   private static long sum(long [] counts) {
202     long sum = 0;
203     for (long count : counts) sum += count;
204     return sum;
205   }
206 
207   private static long [] initializeZeros(int n) {
208     long [] zeros = new long [n];
209     for (int i=0; i<n; i++) {
210       zeros[i] = 0L;
211     }
212     return zeros;
213   }
214 }