001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.io.hfile; 020 021import java.util.Arrays; 022import java.util.concurrent.atomic.AtomicLong; 023import java.util.concurrent.atomic.LongAdder; 024import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram; 025import org.apache.yetus.audience.InterfaceAudience; 026 027 028/** 029 * Class that implements cache metrics. 030 */ 031@InterfaceAudience.Private 032public class CacheStats { 033 034 /** Sliding window statistics. The number of metric periods to include in 035 * sliding window hit ratio calculations. 036 */ 037 static final int DEFAULT_WINDOW_PERIODS = 5; 038 039 /** The number of getBlock requests that were cache hits */ 040 private final LongAdder hitCount = new LongAdder(); 041 042 /** The number of getBlock requests that were cache hits from primary replica */ 043 private final LongAdder primaryHitCount = new LongAdder(); 044 045 /** 046 * The number of getBlock requests that were cache hits, but only from 047 * requests that were set to use the block cache. This is because all reads 048 * attempt to read from the block cache even if they will not put new blocks 049 * into the block cache. See HBASE-2253 for more information. 050 */ 051 private final LongAdder hitCachingCount = new LongAdder(); 052 053 /** The number of getBlock requests that were cache misses */ 054 private final LongAdder missCount = new LongAdder(); 055 056 /** The number of getBlock requests for primary replica that were cache misses */ 057 private final LongAdder primaryMissCount = new LongAdder(); 058 /** 059 * The number of getBlock requests that were cache misses, but only from 060 * requests that were set to use the block cache. 061 */ 062 private final LongAdder missCachingCount = new LongAdder(); 063 064 /** The number of times an eviction has occurred */ 065 private final LongAdder evictionCount = new LongAdder(); 066 067 /** The total number of blocks that have been evicted */ 068 private final LongAdder evictedBlockCount = new LongAdder(); 069 070 /** The total number of blocks for primary replica that have been evicted */ 071 private final LongAdder primaryEvictedBlockCount = new LongAdder(); 072 073 /** The total number of blocks that were not inserted. */ 074 private final AtomicLong failedInserts = new AtomicLong(0); 075 076 /** Per Block Type Counts */ 077 private final LongAdder dataMissCount = new LongAdder(); 078 private final LongAdder leafIndexMissCount = new LongAdder(); 079 private final LongAdder bloomChunkMissCount = new LongAdder(); 080 private final LongAdder metaMissCount = new LongAdder(); 081 private final LongAdder rootIndexMissCount = new LongAdder(); 082 private final LongAdder intermediateIndexMissCount = new LongAdder(); 083 private final LongAdder fileInfoMissCount = new LongAdder(); 084 private final LongAdder generalBloomMetaMissCount = new LongAdder(); 085 private final LongAdder deleteFamilyBloomMissCount = new LongAdder(); 086 private final LongAdder trailerMissCount = new LongAdder(); 087 088 private final LongAdder dataHitCount = new LongAdder(); 089 private final LongAdder leafIndexHitCount = new LongAdder(); 090 private final LongAdder bloomChunkHitCount = new LongAdder(); 091 private final LongAdder metaHitCount = new LongAdder(); 092 private final LongAdder rootIndexHitCount = new LongAdder(); 093 private final LongAdder intermediateIndexHitCount = new LongAdder(); 094 private final LongAdder fileInfoHitCount = new LongAdder(); 095 private final LongAdder generalBloomMetaHitCount = new LongAdder(); 096 private final LongAdder deleteFamilyBloomHitCount = new LongAdder(); 097 private final LongAdder trailerHitCount = new LongAdder(); 098 099 /** 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 = new long[numPeriodsInWindow]; 132 this.hitCachingCounts = new long[numPeriodsInWindow]; 133 this.requestCounts = new long[numPeriodsInWindow]; 134 this.requestCachingCounts = new long[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.sum(); 267 } 268 269 public long getLeafIndexMissCount() { 270 return leafIndexMissCount.sum(); 271 } 272 273 public long getBloomChunkMissCount() { 274 return bloomChunkMissCount.sum(); 275 } 276 277 public long getMetaMissCount() { 278 return metaMissCount.sum(); 279 } 280 281 public long getRootIndexMissCount() { 282 return rootIndexMissCount.sum(); 283 } 284 285 public long getIntermediateIndexMissCount() { 286 return intermediateIndexMissCount.sum(); 287 } 288 289 public long getFileInfoMissCount() { 290 return fileInfoMissCount.sum(); 291 } 292 293 public long getGeneralBloomMetaMissCount() { 294 return generalBloomMetaMissCount.sum(); 295 } 296 297 public long getDeleteFamilyBloomMissCount() { 298 return deleteFamilyBloomMissCount.sum(); 299 } 300 301 public long getTrailerMissCount() { 302 return trailerMissCount.sum(); 303 } 304 305 public long getDataHitCount() { 306 return dataHitCount.sum(); 307 } 308 309 public long getLeafIndexHitCount() { 310 return leafIndexHitCount.sum(); 311 } 312 313 public long getBloomChunkHitCount() { 314 return bloomChunkHitCount.sum(); 315 } 316 317 public long getMetaHitCount() { 318 return metaHitCount.sum(); 319 } 320 321 public long getRootIndexHitCount() { 322 return rootIndexHitCount.sum(); 323 } 324 325 public long getIntermediateIndexHitCount() { 326 return intermediateIndexHitCount.sum(); 327 } 328 329 public long getFileInfoHitCount() { 330 return fileInfoHitCount.sum(); 331 } 332 333 public long getGeneralBloomMetaHitCount() { 334 return generalBloomMetaHitCount.sum(); 335 } 336 337 public long getDeleteFamilyBloomHitCount() { 338 return deleteFamilyBloomHitCount.sum(); 339 } 340 341 public long getTrailerHitCount() { 342 return trailerHitCount.sum(); 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.sum(); 355 } 356 357 public long getPrimaryMissCount() { 358 return primaryMissCount.sum(); 359 } 360 361 public long getMissCachingCount() { 362 return missCachingCount.sum(); 363 } 364 365 public long getHitCount() { 366 return hitCount.sum(); 367 } 368 369 public long getPrimaryHitCount() { 370 return primaryHitCount.sum(); 371 } 372 373 public long getHitCachingCount() { 374 return hitCachingCount.sum(); 375 } 376 377 public long getEvictionCount() { 378 return evictionCount.sum(); 379 } 380 381 public long getEvictedCount() { 382 return this.evictedBlockCount.sum(); 383 } 384 385 public long getPrimaryEvictedCount() { 386 return primaryEvictedBlockCount.sum(); 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 return Arrays.stream(counts).sum(); 491 } 492}