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    /** The number of metrics periods to include in window */
65    private final int numPeriodsInWindow;
66    /** Hit counts for each period in window */
67    private final long [] hitCounts;
68    /** Caching hit counts for each period in window */
69    private final long [] hitCachingCounts;
70    /** Access counts for each period in window */
71    private final long [] requestCounts;
72    /** Caching access counts for each period in window */
73    private final long [] requestCachingCounts;
74    /** Last hit count read */
75    private long lastHitCount = 0;
76    /** Last hit caching count read */
77    private long lastHitCachingCount = 0;
78    /** Last request count read */
79    private long lastRequestCount = 0;
80    /** Last request caching count read */
81    private long lastRequestCachingCount = 0;
82    /** Current window index (next to be updated) */
83    private int windowIndex = 0;
84  
85    public CacheStats() {
86      this(DEFAULT_WINDOW_PERIODS);
87    }
88  
89    public CacheStats(int numPeriodsInWindow) {
90      this.numPeriodsInWindow = numPeriodsInWindow;
91      this.hitCounts = initializeZeros(numPeriodsInWindow);
92      this.hitCachingCounts = initializeZeros(numPeriodsInWindow);
93      this.requestCounts = initializeZeros(numPeriodsInWindow);
94      this.requestCachingCounts = initializeZeros(numPeriodsInWindow);
95    }
96  
97    public void miss(boolean caching) {
98      missCount.incrementAndGet();
99      if (caching) missCachingCount.incrementAndGet();
100   }
101 
102   @Override
103   public String toString() {
104     return "hitCount=" + getHitCount() + ", hitCachingCount=" + getHitCachingCount() +
105       ", missCount=" + getMissCount() + ", missCachingCount=" + getMissCachingCount() +
106       ", evictionCount=" + getEvictionCount() +
107       ", evictedBlockCount=" + getEvictedCount();
108   }
109 
110   public void hit(boolean caching) {
111     hitCount.incrementAndGet();
112     if (caching) hitCachingCount.incrementAndGet();
113   }
114 
115   public void evict() {
116     evictionCount.incrementAndGet();
117   }
118 
119   public void evicted() {
120     evictedBlockCount.incrementAndGet();
121   }
122 
123   public long failInsert() {
124     return failedInserts.incrementAndGet();
125   }
126 
127   public long getRequestCount() {
128     return getHitCount() + getMissCount();
129   }
130 
131   public long getRequestCachingCount() {
132     return getHitCachingCount() + getMissCachingCount();
133   }
134 
135   public long getMissCount() {
136     return missCount.get();
137   }
138 
139   public long getMissCachingCount() {
140     return missCachingCount.get();
141   }
142 
143   public long getHitCount() {
144     return hitCount.get();
145   }
146 
147   public long getHitCachingCount() {
148     return hitCachingCount.get();
149   }
150 
151   public long getEvictionCount() {
152     return evictionCount.get();
153   }
154 
155   public long getEvictedCount() {
156     return evictedBlockCount.get();
157   }
158 
159   public double getHitRatio() {
160     return ((float)getHitCount()/(float)getRequestCount());
161   }
162 
163   public double getHitCachingRatio() {
164     return ((float)getHitCachingCount()/(float)getRequestCachingCount());
165   }
166 
167   public double getMissRatio() {
168     return ((float)getMissCount()/(float)getRequestCount());
169   }
170 
171   public double getMissCachingRatio() {
172     return ((float)getMissCachingCount()/(float)getRequestCachingCount());
173   }
174 
175   public double evictedPerEviction() {
176     return ((float)getEvictedCount()/(float)getEvictionCount());
177   }
178 
179   public long getFailedInserts() {
180     return failedInserts.get();
181   }
182 
183   public void rollMetricsPeriod() {
184     hitCounts[windowIndex] = getHitCount() - lastHitCount;
185     lastHitCount = getHitCount();
186     hitCachingCounts[windowIndex] =
187       getHitCachingCount() - lastHitCachingCount;
188     lastHitCachingCount = getHitCachingCount();
189     requestCounts[windowIndex] = getRequestCount() - lastRequestCount;
190     lastRequestCount = getRequestCount();
191     requestCachingCounts[windowIndex] =
192       getRequestCachingCount() - lastRequestCachingCount;
193     lastRequestCachingCount = getRequestCachingCount();
194     windowIndex = (windowIndex + 1) % numPeriodsInWindow;
195   }
196 
197   public long getSumHitCountsPastNPeriods() {
198     return sum(hitCounts);
199   }
200 
201   public long getSumRequestCountsPastNPeriods() {
202     return sum(requestCounts);
203   }
204 
205   public long getSumHitCachingCountsPastNPeriods() {
206     return sum(hitCachingCounts);
207   }
208 
209   public long getSumRequestCachingCountsPastNPeriods() {
210     return sum(requestCachingCounts);
211   }
212 
213   public double getHitRatioPastNPeriods() {
214     double ratio = ((double)sum(hitCounts)/(double)sum(requestCounts));
215     return Double.isNaN(ratio) ? 0 : ratio;
216   }
217 
218   public double getHitCachingRatioPastNPeriods() {
219     double ratio =
220       ((double)sum(hitCachingCounts)/(double)sum(requestCachingCounts));
221     return Double.isNaN(ratio) ? 0 : ratio;
222   }
223 
224   private static long sum(long [] counts) {
225     long sum = 0;
226     for (long count : counts) sum += count;
227     return sum;
228   }
229 
230   private static long [] initializeZeros(int n) {
231     long [] zeros = new long [n];
232     for (int i=0; i<n; i++) {
233       zeros[i] = 0L;
234     }
235     return zeros;
236   }
237 }