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; 024 025import org.apache.yetus.audience.InterfaceAudience; 026import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram; 027 028 029/** 030 * Class that implements cache metrics. 031 */ 032@InterfaceAudience.Private 033public class CacheStats { 034 035 /** Sliding window statistics. The number of metric periods to include in 036 * sliding window hit ratio calculations. 037 */ 038 static final int DEFAULT_WINDOW_PERIODS = 5; 039 040 /** The number of getBlock requests that were cache hits */ 041 private final LongAdder hitCount = new LongAdder(); 042 043 /** The number of getBlock requests that were cache hits from primary replica */ 044 private final LongAdder primaryHitCount = new LongAdder(); 045 046 /** 047 * The number of getBlock requests that were cache hits, but only from 048 * requests that were set to use the block cache. This is because all reads 049 * attempt to read from the block cache even if they will not put new blocks 050 * into the block cache. See HBASE-2253 for more information. 051 */ 052 private final LongAdder hitCachingCount = new LongAdder(); 053 054 /** The number of getBlock requests that were cache misses */ 055 private final LongAdder missCount = new LongAdder(); 056 057 /** The number of getBlock requests for primary replica that were cache misses */ 058 private final LongAdder primaryMissCount = new LongAdder(); 059 /** 060 * The number of getBlock requests that were cache misses, but only from 061 * requests that were set to use the block cache. 062 */ 063 private final LongAdder missCachingCount = new LongAdder(); 064 065 /** The number of times an eviction has occurred */ 066 private final LongAdder evictionCount = new LongAdder(); 067 068 /** The total number of blocks that have been evicted */ 069 private final LongAdder evictedBlockCount = new LongAdder(); 070 071 /** The total number of blocks for primary replica that have been evicted */ 072 private final LongAdder primaryEvictedBlockCount = new LongAdder(); 073 074 /** The total number of blocks that were not inserted. */ 075 private final AtomicLong failedInserts = new AtomicLong(0); 076 077 /** Per Block Type Counts */ 078 private final LongAdder dataMissCount = new LongAdder(); 079 private final LongAdder leafIndexMissCount = new LongAdder(); 080 private final LongAdder bloomChunkMissCount = new LongAdder(); 081 private final LongAdder metaMissCount = new LongAdder(); 082 private final LongAdder rootIndexMissCount = new LongAdder(); 083 private final LongAdder intermediateIndexMissCount = new LongAdder(); 084 private final LongAdder fileInfoMissCount = new LongAdder(); 085 private final LongAdder generalBloomMetaMissCount = new LongAdder(); 086 private final LongAdder deleteFamilyBloomMissCount = new LongAdder(); 087 private final LongAdder trailerMissCount = new LongAdder(); 088 089 private final LongAdder dataHitCount = new LongAdder(); 090 private final LongAdder leafIndexHitCount = new LongAdder(); 091 private final LongAdder bloomChunkHitCount = new LongAdder(); 092 private final LongAdder metaHitCount = new LongAdder(); 093 private final LongAdder rootIndexHitCount = new LongAdder(); 094 private final LongAdder intermediateIndexHitCount = new LongAdder(); 095 private final LongAdder fileInfoHitCount = new LongAdder(); 096 private final LongAdder generalBloomMetaHitCount = new LongAdder(); 097 private final LongAdder deleteFamilyBloomHitCount = new LongAdder(); 098 private final LongAdder trailerHitCount = new LongAdder(); 099 100 /** The number of metrics periods to include in window */ 101 private final int numPeriodsInWindow; 102 /** Hit counts for each period in window */ 103 private final long [] hitCounts; 104 /** Caching hit counts for each period in window */ 105 private final long [] hitCachingCounts; 106 /** Access counts for each period in window */ 107 private final long [] requestCounts; 108 /** Caching access counts for each period in window */ 109 private final long [] requestCachingCounts; 110 /** Last hit count read */ 111 private long lastHitCount = 0; 112 /** Last hit caching count read */ 113 private long lastHitCachingCount = 0; 114 /** Last request count read */ 115 private long lastRequestCount = 0; 116 /** Last request caching count read */ 117 private long lastRequestCachingCount = 0; 118 /** Current window index (next to be updated) */ 119 private int windowIndex = 0; 120 /** 121 * Keep running age at eviction time 122 */ 123 private FastLongHistogram ageAtEviction; 124 private long startTime = System.nanoTime(); 125 126 public CacheStats(final String name) { 127 this(name, DEFAULT_WINDOW_PERIODS); 128 } 129 130 public CacheStats(final String name, int numPeriodsInWindow) { 131 this.numPeriodsInWindow = numPeriodsInWindow; 132 this.hitCounts = new long[numPeriodsInWindow]; 133 this.hitCachingCounts = new long[numPeriodsInWindow]; 134 this.requestCounts = new long[numPeriodsInWindow]; 135 this.requestCachingCounts = new long[numPeriodsInWindow]; 136 this.ageAtEviction = new FastLongHistogram(); 137 } 138 139 @Override 140 public String toString() { 141 AgeSnapshot snapshot = getAgeAtEvictionSnapshot(); 142 return "hitCount=" + getHitCount() + ", hitCachingCount=" + getHitCachingCount() + 143 ", missCount=" + getMissCount() + ", missCachingCount=" + getMissCachingCount() + 144 ", evictionCount=" + getEvictionCount() + 145 ", evictedBlockCount=" + getEvictedCount() + 146 ", primaryMissCount=" + getPrimaryMissCount() + 147 ", primaryHitCount=" + getPrimaryHitCount() + 148 ", evictedAgeMean=" + snapshot.getMean(); 149 } 150 151 152 public void miss(boolean caching, boolean primary, BlockType type) { 153 missCount.increment(); 154 if (primary) primaryMissCount.increment(); 155 if (caching) missCachingCount.increment(); 156 if (type == null) { 157 return; 158 } 159 switch (type) { 160 case DATA: 161 case ENCODED_DATA: 162 dataMissCount.increment(); 163 break; 164 case LEAF_INDEX: 165 leafIndexMissCount.increment(); 166 break; 167 case BLOOM_CHUNK: 168 bloomChunkMissCount.increment(); 169 break; 170 case META: 171 metaMissCount.increment(); 172 break; 173 case INTERMEDIATE_INDEX: 174 intermediateIndexMissCount.increment(); 175 break; 176 case ROOT_INDEX: 177 rootIndexMissCount.increment(); 178 break; 179 case FILE_INFO: 180 fileInfoMissCount.increment(); 181 break; 182 case GENERAL_BLOOM_META: 183 generalBloomMetaMissCount.increment(); 184 break; 185 case DELETE_FAMILY_BLOOM_META: 186 deleteFamilyBloomMissCount.increment(); 187 break; 188 case TRAILER: 189 trailerMissCount.increment(); 190 break; 191 default: 192 // If there's a new type that's fine 193 // Ignore it for now. This is metrics don't exception. 194 break; 195 } 196 } 197 198 public void hit(boolean caching, boolean primary, BlockType type) { 199 hitCount.increment(); 200 if (primary) primaryHitCount.increment(); 201 if (caching) hitCachingCount.increment(); 202 203 204 if (type == null) { 205 return; 206 } 207 switch (type) { 208 case DATA: 209 case ENCODED_DATA: 210 dataHitCount.increment(); 211 break; 212 case LEAF_INDEX: 213 leafIndexHitCount.increment(); 214 break; 215 case BLOOM_CHUNK: 216 bloomChunkHitCount.increment(); 217 break; 218 case META: 219 metaHitCount.increment(); 220 break; 221 case INTERMEDIATE_INDEX: 222 intermediateIndexHitCount.increment(); 223 break; 224 case ROOT_INDEX: 225 rootIndexHitCount.increment(); 226 break; 227 case FILE_INFO: 228 fileInfoHitCount.increment(); 229 break; 230 case GENERAL_BLOOM_META: 231 generalBloomMetaHitCount.increment(); 232 break; 233 case DELETE_FAMILY_BLOOM_META: 234 deleteFamilyBloomHitCount.increment(); 235 break; 236 case TRAILER: 237 trailerHitCount.increment(); 238 break; 239 default: 240 // If there's a new type that's fine 241 // Ignore it for now. This is metrics don't exception. 242 break; 243 } 244 } 245 246 public void evict() { 247 evictionCount.increment(); 248 } 249 250 public void evicted(final long t, boolean primary) { 251 if (t > this.startTime) { 252 this.ageAtEviction.add((t - this.startTime) / BlockCacheUtil.NANOS_PER_SECOND, 1); 253 } 254 this.evictedBlockCount.increment(); 255 if (primary) { 256 primaryEvictedBlockCount.increment(); 257 } 258 } 259 260 public long failInsert() { 261 return failedInserts.incrementAndGet(); 262 } 263 264 265 // All of the counts of misses and hits. 266 public long getDataMissCount() { 267 return dataMissCount.sum(); 268 } 269 270 public long getLeafIndexMissCount() { 271 return leafIndexMissCount.sum(); 272 } 273 274 public long getBloomChunkMissCount() { 275 return bloomChunkMissCount.sum(); 276 } 277 278 public long getMetaMissCount() { 279 return metaMissCount.sum(); 280 } 281 282 public long getRootIndexMissCount() { 283 return rootIndexMissCount.sum(); 284 } 285 286 public long getIntermediateIndexMissCount() { 287 return intermediateIndexMissCount.sum(); 288 } 289 290 public long getFileInfoMissCount() { 291 return fileInfoMissCount.sum(); 292 } 293 294 public long getGeneralBloomMetaMissCount() { 295 return generalBloomMetaMissCount.sum(); 296 } 297 298 public long getDeleteFamilyBloomMissCount() { 299 return deleteFamilyBloomMissCount.sum(); 300 } 301 302 public long getTrailerMissCount() { 303 return trailerMissCount.sum(); 304 } 305 306 public long getDataHitCount() { 307 return dataHitCount.sum(); 308 } 309 310 public long getLeafIndexHitCount() { 311 return leafIndexHitCount.sum(); 312 } 313 314 public long getBloomChunkHitCount() { 315 return bloomChunkHitCount.sum(); 316 } 317 318 public long getMetaHitCount() { 319 return metaHitCount.sum(); 320 } 321 322 public long getRootIndexHitCount() { 323 return rootIndexHitCount.sum(); 324 } 325 326 public long getIntermediateIndexHitCount() { 327 return intermediateIndexHitCount.sum(); 328 } 329 330 public long getFileInfoHitCount() { 331 return fileInfoHitCount.sum(); 332 } 333 334 public long getGeneralBloomMetaHitCount() { 335 return generalBloomMetaHitCount.sum(); 336 } 337 338 public long getDeleteFamilyBloomHitCount() { 339 return deleteFamilyBloomHitCount.sum(); 340 } 341 342 public long getTrailerHitCount() { 343 return trailerHitCount.sum(); 344 } 345 346 public long getRequestCount() { 347 return getHitCount() + getMissCount(); 348 } 349 350 public long getRequestCachingCount() { 351 return getHitCachingCount() + getMissCachingCount(); 352 } 353 354 public long getMissCount() { 355 return missCount.sum(); 356 } 357 358 public long getPrimaryMissCount() { 359 return primaryMissCount.sum(); 360 } 361 362 public long getMissCachingCount() { 363 return missCachingCount.sum(); 364 } 365 366 public long getHitCount() { 367 return hitCount.sum(); 368 } 369 370 public long getPrimaryHitCount() { 371 return primaryHitCount.sum(); 372 } 373 374 public long getHitCachingCount() { 375 return hitCachingCount.sum(); 376 } 377 378 public long getEvictionCount() { 379 return evictionCount.sum(); 380 } 381 382 public long getEvictedCount() { 383 return this.evictedBlockCount.sum(); 384 } 385 386 public long getPrimaryEvictedCount() { 387 return primaryEvictedBlockCount.sum(); 388 } 389 390 public double getHitRatio() { 391 double requestCount = getRequestCount(); 392 393 if (requestCount == 0) { 394 return 0; 395 } 396 397 return getHitCount() / requestCount; 398 } 399 400 public double getHitCachingRatio() { 401 double requestCachingCount = getRequestCachingCount(); 402 403 if (requestCachingCount == 0) { 404 return 0; 405 } 406 407 return getHitCachingCount() / requestCachingCount; 408 } 409 410 public double getMissRatio() { 411 double requestCount = getRequestCount(); 412 413 if (requestCount == 0) { 414 return 0; 415 } 416 417 return getMissCount() / requestCount; 418 } 419 420 public double getMissCachingRatio() { 421 double requestCachingCount = getRequestCachingCount(); 422 423 if (requestCachingCount == 0) { 424 return 0; 425 } 426 427 return getMissCachingCount() / requestCachingCount; 428 } 429 430 public double evictedPerEviction() { 431 double evictionCount = getEvictionCount(); 432 433 if (evictionCount == 0) { 434 return 0; 435 } 436 437 return getEvictedCount() / evictionCount; 438 } 439 440 public long getFailedInserts() { 441 return failedInserts.get(); 442 } 443 444 public void rollMetricsPeriod() { 445 hitCounts[windowIndex] = getHitCount() - lastHitCount; 446 lastHitCount = getHitCount(); 447 hitCachingCounts[windowIndex] = 448 getHitCachingCount() - lastHitCachingCount; 449 lastHitCachingCount = getHitCachingCount(); 450 requestCounts[windowIndex] = getRequestCount() - lastRequestCount; 451 lastRequestCount = getRequestCount(); 452 requestCachingCounts[windowIndex] = 453 getRequestCachingCount() - lastRequestCachingCount; 454 lastRequestCachingCount = getRequestCachingCount(); 455 windowIndex = (windowIndex + 1) % numPeriodsInWindow; 456 } 457 458 public long getSumHitCountsPastNPeriods() { 459 return sum(hitCounts); 460 } 461 462 public long getSumRequestCountsPastNPeriods() { 463 return sum(requestCounts); 464 } 465 466 public long getSumHitCachingCountsPastNPeriods() { 467 return sum(hitCachingCounts); 468 } 469 470 public long getSumRequestCachingCountsPastNPeriods() { 471 return sum(requestCachingCounts); 472 } 473 474 public double getHitRatioPastNPeriods() { 475 double ratio = ((double)getSumHitCountsPastNPeriods() / 476 (double)getSumRequestCountsPastNPeriods()); 477 return Double.isNaN(ratio) ? 0 : ratio; 478 } 479 480 public double getHitCachingRatioPastNPeriods() { 481 double ratio = ((double)getSumHitCachingCountsPastNPeriods() / 482 (double)getSumRequestCachingCountsPastNPeriods()); 483 return Double.isNaN(ratio) ? 0 : ratio; 484 } 485 486 public AgeSnapshot getAgeAtEvictionSnapshot() { 487 return new AgeSnapshot(this.ageAtEviction); 488 } 489 490 private static long sum(long[] counts) { 491 return Arrays.stream(counts).sum(); 492 } 493}